@parcel/graph 2.8.4-nightly.2926 → 2.8.4-nightly.2939

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.
@@ -4,62 +4,45 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = exports.SharedTypeMap = exports.NodeTypeMap = exports.EdgeTypeMap = void 0;
7
-
8
7
  function _assert() {
9
8
  const data = _interopRequireDefault(require("assert"));
10
-
11
9
  _assert = function () {
12
10
  return data;
13
11
  };
14
-
15
12
  return data;
16
13
  }
17
-
18
14
  function _nullthrows() {
19
15
  const data = _interopRequireDefault(require("nullthrows"));
20
-
21
16
  _nullthrows = function () {
22
17
  return data;
23
18
  };
24
-
25
19
  return data;
26
20
  }
27
-
28
21
  var _sharedBuffer = require("./shared-buffer");
29
-
30
22
  var _types = require("./types");
31
-
32
23
  var _Graph = require("./Graph");
33
-
34
24
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
35
-
25
+ /** The address of the node in the nodes map. */
26
+ /** The address of the edge in the edges map. */
27
+ // eslint-disable-next-line no-unused-vars
28
+ // eslint-disable-next-line no-unused-vars
36
29
  /** The upper bound above which capacity should be increased. */
37
30
  const LOAD_FACTOR = 0.7;
38
31
  /** The lower bound below which capacity should be decreased. */
39
-
40
32
  const UNLOAD_FACTOR = 0.3;
41
33
  /** The max amount by which to grow the capacity. */
42
-
43
34
  const MAX_GROW_FACTOR = 8;
44
35
  /** The min amount by which to grow the capacity. */
45
-
46
36
  const MIN_GROW_FACTOR = 2;
47
37
  /** The amount by which to shrink the capacity. */
48
-
49
38
  const SHRINK_FACTOR = 0.5;
50
-
51
39
  class AdjacencyList {
52
- #nodes
53
- /*: NodeTypeMap<TEdgeType | NullEdgeType> */
54
- ;
55
- #edges
56
- /*: EdgeTypeMap<TEdgeType | NullEdgeType> */
57
- ;
40
+ #nodes /*: NodeTypeMap<TEdgeType | NullEdgeType> */;
41
+ #edges /*: EdgeTypeMap<TEdgeType | NullEdgeType> */;
58
42
 
59
43
  constructor(opts) {
60
44
  let nodes;
61
45
  let edges;
62
-
63
46
  if (opts !== null && opts !== void 0 && opts.nodes) {
64
47
  ({
65
48
  nodes,
@@ -78,29 +61,25 @@ class AdjacencyList {
78
61
  this.#edges = new EdgeTypeMap(edgeCapacity);
79
62
  }
80
63
  }
64
+
81
65
  /**
82
66
  * Create a new `AdjacencyList` from the given options.
83
67
  */
84
-
85
-
86
68
  static deserialize(opts) {
87
69
  return new AdjacencyList(opts);
88
70
  }
71
+
89
72
  /**
90
73
  * Returns a serializable object of the nodes and edges in the graph.
91
74
  */
92
-
93
-
94
75
  serialize() {
95
76
  return {
96
77
  nodes: this.#nodes.data,
97
78
  edges: this.#edges.data
98
79
  };
99
80
  }
100
-
101
81
  get stats() {
102
82
  let buckets = new Map();
103
-
104
83
  for (let {
105
84
  from,
106
85
  to,
@@ -113,17 +92,14 @@ class AdjacencyList {
113
92
  bucket.add(key);
114
93
  buckets.set(hash, bucket);
115
94
  }
116
-
117
95
  let maxCollisions = 0;
118
96
  let collisions = 0;
119
97
  let distribution = 0;
120
-
121
98
  for (let bucket of buckets.values()) {
122
99
  maxCollisions = Math.max(maxCollisions, bucket.size - 1);
123
100
  collisions += bucket.size - 1;
124
101
  distribution += bucket.size * (bucket.size + 1) / 2;
125
102
  }
126
-
127
103
  let uniformity = distribution / (this.#edges.count / (2 * this.#edges.capacity) * (this.#edges.count + 2 * this.#edges.capacity - 1));
128
104
  return {
129
105
  nodes: (0, _types.fromNodeId)(this.#nodes.nextId),
@@ -143,83 +119,82 @@ class AdjacencyList {
143
119
  uniformity: Math.round(uniformity * 100) / 100 || 0
144
120
  };
145
121
  }
122
+
146
123
  /**
147
124
  * Resize the internal nodes array.
148
125
  *
149
126
  * This is used in `addNode` when the `numNodes` meets or exceeds
150
127
  * the allocated size of the `nodes` array.
151
128
  */
152
-
153
-
154
129
  resizeNodes(size) {
155
- let nodes = this.#nodes; // Allocate the required space for a `nodes` map of the given `size`.
156
-
157
- this.#nodes = new NodeTypeMap(size); // Copy the existing nodes into the new array.
158
-
130
+ let nodes = this.#nodes;
131
+ // Allocate the required space for a `nodes` map of the given `size`.
132
+ this.#nodes = new NodeTypeMap(size);
133
+ // Copy the existing nodes into the new array.
159
134
  this.#nodes.set(nodes.data);
160
135
  }
136
+
161
137
  /**
162
138
  * Resize the internal edges array.
163
139
  *
164
140
  * This is used in `addEdge` when the `numEdges` meets or exceeds
165
141
  * the allocated size of the `edges` array.
166
142
  */
167
-
168
-
169
143
  resizeEdges(size) {
170
144
  // Allocate the required space for new `nodes` and `edges` maps.
171
145
  let copy = new AdjacencyList({
172
146
  nodeCapacity: this.#nodes.capacity,
173
147
  edgeCapacity: size
174
- }); // Copy the existing edges into the new array.
148
+ });
175
149
 
150
+ // Copy the existing edges into the new array.
176
151
  copy.#nodes.nextId = this.#nodes.nextId;
177
- this.#edges.forEach(edge => void copy.addEdge(this.#edges.from(edge), this.#edges.to(edge), this.#edges.typeOf(edge))); // We expect to preserve the same number of edges.
152
+ this.#edges.forEach(edge => void copy.addEdge(this.#edges.from(edge), this.#edges.to(edge), this.#edges.typeOf(edge)));
178
153
 
179
- (0, _assert().default)(this.#edges.count === copy.#edges.count, `Edge mismatch! ${this.#edges.count} does not match ${copy.#edges.count}.`); // Finally, copy the new data arrays over to this graph.
154
+ // We expect to preserve the same number of edges.
155
+ (0, _assert().default)(this.#edges.count === copy.#edges.count, `Edge mismatch! ${this.#edges.count} does not match ${copy.#edges.count}.`);
180
156
 
157
+ // Finally, copy the new data arrays over to this graph.
181
158
  this.#nodes = copy.#nodes;
182
159
  this.#edges = copy.#edges;
183
160
  }
161
+
184
162
  /**
185
163
  * Adds a node to the graph.
186
164
  *
187
165
  * Returns the id of the added node.
188
166
  */
189
-
190
-
191
167
  addNode() {
192
- let id = this.#nodes.getId(); // If we're in danger of overflowing the `nodes` array, resize it.
193
-
168
+ let id = this.#nodes.getId();
169
+ // If we're in danger of overflowing the `nodes` array, resize it.
194
170
  if (this.#nodes.load > LOAD_FACTOR) {
195
171
  this.resizeNodes(increaseNodeCapacity(this.#nodes.capacity));
196
172
  }
197
-
198
173
  return id;
199
174
  }
175
+
200
176
  /**
201
177
  * Adds an edge to the graph.
202
178
  *
203
179
  * Returns `true` if the edge was added,
204
180
  * or `false` if the edge already exists.
205
181
  */
206
-
207
-
208
182
  addEdge(from, to, type = 1) {
209
183
  (0, _assert().default)(type > 0, `Unsupported edge type ${type}`);
210
184
  let hash = this.#edges.hash(from, to, type);
211
- let edge = this.#edges.addressOf(hash, from, to, type); // The edge is already in the graph; do nothing.
185
+ let edge = this.#edges.addressOf(hash, from, to, type);
212
186
 
187
+ // The edge is already in the graph; do nothing.
213
188
  if (edge !== null) return false;
214
- let capacity = this.#edges.capacity; // We add 1 to account for the edge we are adding.
215
-
216
- let count = this.#edges.count + 1; // Since the space occupied by deleted edges isn't reclaimed,
189
+ let capacity = this.#edges.capacity;
190
+ // We add 1 to account for the edge we are adding.
191
+ let count = this.#edges.count + 1;
192
+ // Since the space occupied by deleted edges isn't reclaimed,
217
193
  // we include them in our count to avoid overflowing the `edges` array.
218
-
219
194
  let deletes = this.#edges.deletes;
220
- let total = count + deletes; // If we have enough space to keep adding edges, we can
195
+ let total = count + deletes;
196
+ // If we have enough space to keep adding edges, we can
221
197
  // put off reclaiming the deleted space until the next resize.
222
-
223
198
  if (this.#edges.getLoad(total) > LOAD_FACTOR) {
224
199
  if (this.#edges.getLoad(deletes) > UNLOAD_FACTOR) {
225
200
  // If we have a significant number of deletes, we compute our new
@@ -229,38 +204,36 @@ class AdjacencyList {
229
204
  this.resizeEdges(getNextEdgeCapacity(capacity, count, this.#edges.getLoad(count)));
230
205
  } else {
231
206
  this.resizeEdges(getNextEdgeCapacity(capacity, total, this.#edges.getLoad(total)));
232
- } // We must rehash because the capacity has changed.
233
-
234
-
207
+ }
208
+ // We must rehash because the capacity has changed.
235
209
  hash = this.#edges.hash(from, to, type);
236
210
  }
237
-
238
211
  let toNode = this.#nodes.addressOf(to, type);
239
212
  let fromNode = this.#nodes.addressOf(from, type);
240
-
241
213
  if (toNode === null || fromNode === null) {
242
214
  // If we're in danger of overflowing the `nodes` array, resize it.
243
215
  if (this.#nodes.load >= LOAD_FACTOR) {
244
- this.resizeNodes(increaseNodeCapacity(this.#nodes.capacity)); // We need to update our indices since the `nodes` array has changed.
245
-
216
+ this.resizeNodes(increaseNodeCapacity(this.#nodes.capacity));
217
+ // We need to update our indices since the `nodes` array has changed.
246
218
  toNode = this.#nodes.addressOf(to, type);
247
219
  fromNode = this.#nodes.addressOf(from, type);
248
220
  }
249
221
  }
250
-
251
222
  if (toNode === null) toNode = this.#nodes.add(to, type);
252
- if (fromNode === null) fromNode = this.#nodes.add(from, type); // Add our new edge to its hash bucket.
223
+ if (fromNode === null) fromNode = this.#nodes.add(from, type);
253
224
 
254
- edge = this.#edges.add(hash, from, to, type); // Link this edge to the node's list of incoming edges.
225
+ // Add our new edge to its hash bucket.
226
+ edge = this.#edges.add(hash, from, to, type);
255
227
 
228
+ // Link this edge to the node's list of incoming edges.
256
229
  let prevIn = this.#nodes.linkIn(toNode, edge);
257
- if (prevIn !== null) this.#edges.linkIn(prevIn, edge); // Link this edge to the node's list of outgoing edges.
230
+ if (prevIn !== null) this.#edges.linkIn(prevIn, edge);
258
231
 
232
+ // Link this edge to the node's list of outgoing edges.
259
233
  let prevOut = this.#nodes.linkOut(fromNode, edge);
260
234
  if (prevOut !== null) this.#edges.linkOut(prevOut, edge);
261
235
  return true;
262
236
  }
263
-
264
237
  *getAllEdges() {
265
238
  for (let edge of this.#edges) {
266
239
  yield {
@@ -270,68 +243,62 @@ class AdjacencyList {
270
243
  };
271
244
  }
272
245
  }
246
+
273
247
  /**
274
248
  * Check if the graph has an edge connecting the `from` and `to` nodes.
275
249
  */
276
-
277
-
278
250
  hasEdge(from, to, type = 1) {
279
251
  let hasEdge = type => {
280
252
  let hash = this.#edges.hash(from, to, type);
281
253
  return this.#edges.addressOf(hash, from, to, type) !== null;
282
254
  };
283
-
284
255
  if (Array.isArray(type)) {
285
256
  return type.some(hasEdge);
286
257
  }
287
-
288
258
  return hasEdge(type);
289
259
  }
260
+
290
261
  /**
291
262
  *
292
263
  */
293
-
294
-
295
264
  removeEdge(from, to, type = 1) {
296
265
  let hash = this.#edges.hash(from, to, type);
297
- let edge = this.#edges.addressOf(hash, from, to, type); // The edge is not in the graph; do nothing.
266
+ let edge = this.#edges.addressOf(hash, from, to, type);
298
267
 
268
+ // The edge is not in the graph; do nothing.
299
269
  if (edge === null) return;
300
270
  let toNode = (0, _nullthrows().default)(this.#nodes.addressOf(to, type));
301
- let fromNode = (0, _nullthrows().default)(this.#nodes.addressOf(from, type)); // Update the terminating node's first and last incoming edges.
302
-
303
- this.#nodes.unlinkIn(toNode, edge, this.#edges.prevIn(edge), this.#edges.nextIn(edge)); // Update the originating node's first and last outgoing edges.
271
+ let fromNode = (0, _nullthrows().default)(this.#nodes.addressOf(from, type));
304
272
 
305
- this.#nodes.unlinkOut(fromNode, edge, this.#edges.prevOut(edge), this.#edges.nextOut(edge)); // Splice the removed edge out of the linked list of edges in the bucket.
273
+ // Update the terminating node's first and last incoming edges.
274
+ this.#nodes.unlinkIn(toNode, edge, this.#edges.prevIn(edge), this.#edges.nextIn(edge));
306
275
 
307
- this.#edges.unlink(hash, edge); // Splice the removed edge out of the linked list of incoming edges.
308
-
309
- this.#edges.unlinkIn(edge); // Splice the removed edge out of the linked list of outgoing edges.
310
-
311
- this.#edges.unlinkOut(edge); // Finally, delete the edge.
276
+ // Update the originating node's first and last outgoing edges.
277
+ this.#nodes.unlinkOut(fromNode, edge, this.#edges.prevOut(edge), this.#edges.nextOut(edge));
312
278
 
279
+ // Splice the removed edge out of the linked list of edges in the bucket.
280
+ this.#edges.unlink(hash, edge);
281
+ // Splice the removed edge out of the linked list of incoming edges.
282
+ this.#edges.unlinkIn(edge);
283
+ // Splice the removed edge out of the linked list of outgoing edges.
284
+ this.#edges.unlinkOut(edge);
285
+ // Finally, delete the edge.
313
286
  this.#edges.delete(edge);
314
287
  }
315
-
316
288
  hasInboundEdges(to) {
317
289
  let node = this.#nodes.head(to);
318
-
319
290
  while (node !== null) {
320
291
  if (this.#nodes.firstIn(node) !== null) return true;
321
292
  node = this.#nodes.next(node);
322
293
  }
323
-
324
294
  return false;
325
295
  }
326
-
327
296
  getInboundEdgesByType(to) {
328
297
  let edges = [];
329
298
  let node = this.#nodes.head(to);
330
-
331
299
  while (node !== null) {
332
300
  let type = this.#nodes.typeOf(node);
333
301
  let edge = this.#nodes.firstIn(node);
334
-
335
302
  while (edge !== null) {
336
303
  let from = this.#edges.from(edge);
337
304
  edges.push({
@@ -340,21 +307,16 @@ class AdjacencyList {
340
307
  });
341
308
  edge = this.#edges.nextIn(edge);
342
309
  }
343
-
344
310
  node = this.#nodes.next(node);
345
311
  }
346
-
347
312
  return edges;
348
313
  }
349
-
350
314
  getOutboundEdgesByType(from) {
351
315
  let edges = [];
352
316
  let node = this.#nodes.head(from);
353
-
354
317
  while (node !== null) {
355
318
  let type = this.#nodes.typeOf(node);
356
319
  let edge = this.#nodes.firstOut(node);
357
-
358
320
  while (edge !== null) {
359
321
  let to = this.#edges.to(edge);
360
322
  edges.push({
@@ -363,87 +325,68 @@ class AdjacencyList {
363
325
  });
364
326
  edge = this.#edges.nextOut(edge);
365
327
  }
366
-
367
328
  node = this.#nodes.next(node);
368
329
  }
369
-
370
330
  return edges;
371
331
  }
332
+
372
333
  /**
373
334
  * Get the list of nodes connected from this node.
374
335
  */
375
-
376
-
377
336
  getNodeIdsConnectedFrom(from, type = 1) {
378
337
  let matches = node => type === _Graph.ALL_EDGE_TYPES || (Array.isArray(type) ? type.includes(this.#nodes.typeOf(node)) : type === this.#nodes.typeOf(node));
379
-
380
338
  let nodes = [];
381
339
  let seen = new Set();
382
340
  let node = this.#nodes.head(from);
383
-
384
341
  while (node !== null) {
385
342
  if (matches(node)) {
386
343
  let edge = this.#nodes.firstOut(node);
387
-
388
344
  while (edge !== null) {
389
345
  let to = this.#edges.to(edge);
390
-
391
346
  if (!seen.has(to)) {
392
347
  nodes.push(to);
393
348
  seen.add(to);
394
349
  }
395
-
396
350
  edge = this.#edges.nextOut(edge);
397
351
  }
398
352
  }
399
-
400
353
  node = this.#nodes.next(node);
401
354
  }
402
-
403
355
  return nodes;
404
356
  }
357
+
405
358
  /**
406
359
  * Get the list of nodes connected to this node.
407
360
  */
408
-
409
-
410
361
  getNodeIdsConnectedTo(to, type = 1) {
411
362
  let matches = node => type === _Graph.ALL_EDGE_TYPES || (Array.isArray(type) ? type.includes(this.#nodes.typeOf(node)) : type === this.#nodes.typeOf(node));
412
-
413
363
  let nodes = [];
414
364
  let seen = new Set();
415
365
  let node = this.#nodes.head(to);
416
-
417
366
  while (node !== null) {
418
367
  if (matches(node)) {
419
368
  let edge = this.#nodes.firstIn(node);
420
-
421
369
  while (edge !== null) {
422
370
  let from = this.#edges.from(edge);
423
-
424
371
  if (!seen.has(from)) {
425
372
  nodes.push(from);
426
373
  seen.add(from);
427
374
  }
428
-
429
375
  edge = this.#edges.nextIn(edge);
430
376
  }
431
377
  }
432
-
433
378
  node = this.#nodes.next(node);
434
379
  }
435
-
436
380
  return nodes;
437
381
  }
438
-
439
382
  inspect() {
440
383
  return {
441
384
  nodes: this.#nodes.inspect(),
442
385
  edges: this.#edges.inspect()
443
386
  };
444
387
  }
445
-
446
388
  }
389
+
447
390
  /**
448
391
  * `SharedTypeMap` is a hashmap of items,
449
392
  * where each item has its own 'type' field.
@@ -483,10 +426,7 @@ class AdjacencyList {
483
426
  * └────┼─────────┴─────────────────┘ │
484
427
  * └─────────────────────────────────────────────┘
485
428
  */
486
-
487
-
488
429
  exports.default = AdjacencyList;
489
-
490
430
  class SharedTypeMap {
491
431
  /**
492
432
  * The header for the `SharedTypeMap` comprises 2 4-byte chunks:
@@ -502,11 +442,10 @@ class SharedTypeMap {
502
442
  */
503
443
  static HEADER_SIZE = 2;
504
444
  /** The offset from the header where the capacity is stored. */
505
-
506
445
  static #CAPACITY = 0;
507
446
  /** The offset from the header where the count is stored. */
508
-
509
447
  static #COUNT = 1;
448
+
510
449
  /**
511
450
  * Each item in `SharedTypeMap` comprises 2 4-byte chunks:
512
451
  *
@@ -519,52 +458,42 @@ class SharedTypeMap {
519
458
  * │ NEXT │ TYPE │
520
459
  * └──────┴──────┘
521
460
  */
522
-
523
461
  static ITEM_SIZE = 2;
524
462
  /** The offset at which a link to the next item in the same bucket is stored. */
525
-
526
463
  static #NEXT = 0;
527
464
  /** The offset at which an item's type is stored. */
528
-
529
465
  static #TYPE = 1;
530
- /** The number of items to accommodate per hash bucket. */
531
466
 
467
+ /** The number of items to accommodate per hash bucket. */
532
468
  static BUCKET_SIZE = 2;
533
-
534
469
  get capacity() {
535
470
  return this.data[SharedTypeMap.#CAPACITY];
536
471
  }
537
-
538
472
  get count() {
539
473
  return this.data[SharedTypeMap.#COUNT];
540
474
  }
541
-
542
475
  get load() {
543
476
  return this.getLoad();
544
477
  }
545
-
546
478
  get length() {
547
479
  return this.getLength();
548
480
  }
549
-
550
481
  get addressableLimit() {
551
482
  return this.constructor.HEADER_SIZE + this.capacity;
552
483
  }
553
-
554
484
  get bufferSize() {
555
485
  return `${(this.data.byteLength / 1024 / 1024).toLocaleString(undefined, {
556
486
  minimumFractionDigits: 2,
557
487
  maximumFractionDigits: 2
558
488
  })} mb`;
559
489
  }
560
-
561
490
  constructor(capacityOrData) {
562
491
  if (typeof capacityOrData === 'number') {
563
492
  let {
564
493
  BYTES_PER_ELEMENT
565
494
  } = Uint32Array;
566
- let CAPACITY = SharedTypeMap.#CAPACITY; // $FlowFixMe[incompatible-call]
567
-
495
+ let CAPACITY = SharedTypeMap.#CAPACITY;
496
+ // $FlowFixMe[incompatible-call]
568
497
  this.data = new Uint32Array(new _sharedBuffer.SharedBuffer(this.getLength(capacityOrData) * BYTES_PER_ELEMENT));
569
498
  this.data[CAPACITY] = capacityOrData;
570
499
  } else {
@@ -572,7 +501,6 @@ class SharedTypeMap {
572
501
  (0, _assert().default)(this.getLength() === this.data.length, 'Data appears corrupt.');
573
502
  }
574
503
  }
575
-
576
504
  set(data) {
577
505
  let {
578
506
  HEADER_SIZE,
@@ -582,37 +510,35 @@ class SharedTypeMap {
582
510
  let COUNT = SharedTypeMap.#COUNT;
583
511
  let CAPACITY = SharedTypeMap.#CAPACITY;
584
512
  let delta = this.capacity - data[CAPACITY];
585
- (0, _assert().default)(delta >= 0, 'Cannot copy to a map with smaller capacity.'); // Copy the header.
513
+ (0, _assert().default)(delta >= 0, 'Cannot copy to a map with smaller capacity.');
586
514
 
587
- this.data.set(data.subarray(COUNT, HEADER_SIZE), COUNT); // Copy the hash table.
515
+ // Copy the header.
516
+ this.data.set(data.subarray(COUNT, HEADER_SIZE), COUNT);
588
517
 
518
+ // Copy the hash table.
589
519
  let toTable = this.data.subarray(HEADER_SIZE, HEADER_SIZE + this.capacity);
590
- toTable.set(data.subarray(HEADER_SIZE, HEADER_SIZE + data[CAPACITY])); // Offset first links to account for the change in table capacity.
591
-
520
+ toTable.set(data.subarray(HEADER_SIZE, HEADER_SIZE + data[CAPACITY]));
521
+ // Offset first links to account for the change in table capacity.
592
522
  let max = toTable.length;
593
-
594
523
  for (let i = 0; i < max; i++) {
595
524
  if (toTable[i]) toTable[i] += delta;
596
- } // Copy the items.
597
-
525
+ }
598
526
 
527
+ // Copy the items.
599
528
  let toItems = this.data.subarray(HEADER_SIZE + this.capacity);
600
- toItems.set(data.subarray(HEADER_SIZE + data[CAPACITY])); // Offset next links to account for the change in table capacity.
601
-
529
+ toItems.set(data.subarray(HEADER_SIZE + data[CAPACITY]));
530
+ // Offset next links to account for the change in table capacity.
602
531
  max = toItems.length;
603
-
604
532
  for (let i = 0; i < max; i += ITEM_SIZE) {
605
533
  if (toItems[i + NEXT]) toItems[i + NEXT] += delta;
606
534
  }
607
535
  }
608
-
609
536
  getLoad(count = this.count) {
610
537
  let {
611
538
  BUCKET_SIZE
612
539
  } = this.constructor;
613
540
  return count / (this.capacity * BUCKET_SIZE);
614
541
  }
615
-
616
542
  getLength(capacity = this.capacity) {
617
543
  let {
618
544
  HEADER_SIZE,
@@ -621,9 +547,8 @@ class SharedTypeMap {
621
547
  } = this.constructor;
622
548
  return capacity + HEADER_SIZE + ITEM_SIZE * BUCKET_SIZE * capacity;
623
549
  }
624
- /** Get the next available address in the map. */
625
-
626
550
 
551
+ /** Get the next available address in the map. */
627
552
  getNextAddress() {
628
553
  let {
629
554
  HEADER_SIZE,
@@ -631,27 +556,23 @@ class SharedTypeMap {
631
556
  } = this.constructor;
632
557
  return HEADER_SIZE + this.capacity + this.count * ITEM_SIZE;
633
558
  }
634
- /** Get the address of the first item with the given hash. */
635
-
636
559
 
560
+ /** Get the address of the first item with the given hash. */
637
561
  head(hash) {
638
562
  let {
639
563
  HEADER_SIZE
640
564
  } = this.constructor;
641
565
  return this.data[HEADER_SIZE + hash] || null;
642
566
  }
643
- /** Get the address of the next item with the same hash as the given item. */
644
-
645
567
 
568
+ /** Get the address of the next item with the same hash as the given item. */
646
569
  next(item) {
647
570
  let NEXT = SharedTypeMap.#NEXT;
648
571
  return this.data[item + NEXT] || null;
649
572
  }
650
-
651
573
  typeOf(item) {
652
574
  return this.data[item + SharedTypeMap.#TYPE];
653
575
  }
654
-
655
576
  link(hash, item, type) {
656
577
  let COUNT = SharedTypeMap.#COUNT;
657
578
  let NEXT = SharedTypeMap.#NEXT;
@@ -661,24 +582,19 @@ class SharedTypeMap {
661
582
  } = this.constructor;
662
583
  this.data[item + TYPE] = type;
663
584
  let prev = this.head(hash);
664
-
665
585
  if (prev !== null) {
666
586
  let next = this.next(prev);
667
-
668
587
  while (next !== null) {
669
588
  prev = next;
670
589
  next = this.next(next);
671
590
  }
672
-
673
591
  this.data[prev + NEXT] = item;
674
592
  } else {
675
593
  // This is the first item in the bucket!
676
594
  this.data[HEADER_SIZE + hash] = item;
677
595
  }
678
-
679
596
  this.data[COUNT]++;
680
597
  }
681
-
682
598
  unlink(hash, item) {
683
599
  let COUNT = SharedTypeMap.#COUNT;
684
600
  let NEXT = SharedTypeMap.#NEXT;
@@ -687,18 +603,16 @@ class SharedTypeMap {
687
603
  HEADER_SIZE
688
604
  } = this.constructor;
689
605
  this.data[item + TYPE] = 0;
690
- let head = this.head(hash); // No bucket to unlink from.
691
-
606
+ let head = this.head(hash);
607
+ // No bucket to unlink from.
692
608
  if (head === null) return;
693
609
  let next = this.next(item);
694
610
  let prev = null;
695
611
  let candidate = head;
696
-
697
612
  while (candidate !== null && candidate !== item) {
698
613
  prev = candidate;
699
614
  candidate = this.next(candidate);
700
615
  }
701
-
702
616
  if (prev !== null && next !== null) {
703
617
  this.data[prev + NEXT] = next;
704
618
  } else if (prev !== null) {
@@ -708,18 +622,15 @@ class SharedTypeMap {
708
622
  } else {
709
623
  this.data[HEADER_SIZE + hash] = 0;
710
624
  }
711
-
712
625
  this.data[item + NEXT] = 0;
713
626
  this.data[COUNT]--;
714
627
  }
715
-
716
628
  forEach(cb) {
717
629
  let max = this.count;
718
630
  let len = this.length;
719
631
  let {
720
632
  ITEM_SIZE
721
633
  } = this.constructor;
722
-
723
634
  for (let i = this.addressableLimit, count = 0; i < len && count < max; i += ITEM_SIZE) {
724
635
  // Skip items that don't have a type.
725
636
  if (this.typeOf(i)) {
@@ -727,20 +638,18 @@ class SharedTypeMap {
727
638
  count++;
728
639
  }
729
640
  }
730
- } // Trick Flow into believing in `Symbol.iterator`.
731
- // See https://github.com/facebook/flow/issues/1163#issuecomment-353523840
641
+ }
732
642
 
643
+ // Trick Flow into believing in `Symbol.iterator`.
644
+ // See https://github.com/facebook/flow/issues/1163#issuecomment-353523840
733
645
  /*:: @@iterator(): Iterator<TAddress> { return ({}: any); } */
734
646
  // $FlowFixMe[unsupported-syntax]
735
-
736
-
737
647
  *[Symbol.iterator]() {
738
648
  let max = this.count;
739
649
  let len = this.length;
740
650
  let {
741
651
  ITEM_SIZE
742
652
  } = this.constructor;
743
-
744
653
  for (let i = this.addressableLimit, count = 0; i < len && count < max; i += ITEM_SIZE) {
745
654
  if (this.data.subarray(i, i + ITEM_SIZE).some(Boolean)) {
746
655
  yield i;
@@ -748,7 +657,6 @@ class SharedTypeMap {
748
657
  }
749
658
  }
750
659
  }
751
-
752
660
  inspect() {
753
661
  const {
754
662
  HEADER_SIZE,
@@ -763,17 +671,14 @@ class SharedTypeMap {
763
671
  data: this.data.subarray(min, max)
764
672
  };
765
673
  }
766
-
767
674
  }
675
+
768
676
  /**
769
677
  * Nodes are stored in a `SharedTypeMap`, keyed on node id plus an edge type.
770
678
  * This means that for any given unique node id, there may be `e` nodes in the
771
679
  * map, where `e` is the number of possible edge types in the graph.
772
680
  */
773
-
774
-
775
681
  exports.SharedTypeMap = SharedTypeMap;
776
-
777
682
  class NodeTypeMap extends SharedTypeMap {
778
683
  /**
779
684
  * In addition to the header defined by `SharedTypeMap`, the header for
@@ -791,8 +696,8 @@ class NodeTypeMap extends SharedTypeMap {
791
696
  */
792
697
  static HEADER_SIZE = 3;
793
698
  /** The offset from the header where the next available node id is stored. */
794
-
795
699
  static #NEXT_ID = 2;
700
+
796
701
  /**
797
702
  * In addition to the item fields defined by `SharedTypeMap`,
798
703
  * each node includes another 4 4-byte chunks:
@@ -810,46 +715,36 @@ class NodeTypeMap extends SharedTypeMap {
810
715
  * │ NEXT │ TYPE │ FIRST_IN │ FIRST_OUT │ LAST_IN │ LAST_OUT │
811
716
  * └──────┴──────┴──────────┴───────────┴─────────┴──────────┘
812
717
  */
813
-
814
718
  static ITEM_SIZE = 6;
815
719
  /** The offset at which a node's first incoming edge of this type is stored. */
816
-
817
720
  static #FIRST_IN = 2;
818
721
  /** The offset at which a node's first outgoing edge of this type is stored. */
819
-
820
722
  static #FIRST_OUT = 3;
821
723
  /** The offset at which a node's last incoming edge of this type is stored. */
822
-
823
724
  static #LAST_IN = 4;
824
725
  /** The offset at which a node's last outgoing edge of this type is stored. */
825
-
826
726
  static #LAST_OUT = 5;
827
- /** The smallest functional node map capacity. */
828
727
 
728
+ /** The smallest functional node map capacity. */
829
729
  static MIN_CAPACITY = 2;
830
730
  /** The largest possible node map capacity. */
831
-
832
- static MAX_CAPACITY = Math.floor( // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length#what_went_wrong
731
+ static MAX_CAPACITY = Math.floor(
732
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length#what_went_wrong
833
733
  (2 ** 31 - 1 - NodeTypeMap.HEADER_SIZE) / NodeTypeMap.ITEM_SIZE / NodeTypeMap.BUCKET_SIZE);
834
-
835
734
  get nextId() {
836
735
  return (0, _types.toNodeId)(this.data[NodeTypeMap.#NEXT_ID]);
837
736
  }
838
-
839
737
  set nextId(nextId) {
840
738
  this.data[NodeTypeMap.#NEXT_ID] = (0, _types.fromNodeId)(nextId);
841
739
  }
842
- /** Get a unique node id. */
843
-
844
740
 
741
+ /** Get a unique node id. */
845
742
  getId() {
846
743
  return (0, _types.toNodeId)(this.data[NodeTypeMap.#NEXT_ID]++);
847
744
  }
848
-
849
745
  getLoad(count = this.count) {
850
746
  return Math.max((0, _types.fromNodeId)(this.nextId) / this.capacity, super.getLoad(count));
851
747
  }
852
-
853
748
  add(node, type) {
854
749
  let index = (0, _types.fromNodeId)(node);
855
750
  (0, _assert().default)(index >= 0 && index < this.data[NodeTypeMap.#NEXT_ID], `Invalid node id ${String(node)} (${this.data[NodeTypeMap.#NEXT_ID]})`);
@@ -857,37 +752,28 @@ class NodeTypeMap extends SharedTypeMap {
857
752
  this.link(node, address, type);
858
753
  return address;
859
754
  }
860
-
861
755
  addressOf(node, type) {
862
756
  let address = this.head(node);
863
-
864
757
  while (address !== null) {
865
758
  if (this.typeOf(address) === type) {
866
759
  return address;
867
760
  }
868
-
869
761
  address = this.next(address);
870
762
  }
871
-
872
763
  return null;
873
764
  }
874
-
875
765
  firstIn(node) {
876
766
  return this.data[node + NodeTypeMap.#FIRST_IN] || null;
877
767
  }
878
-
879
768
  firstOut(node) {
880
769
  return this.data[node + NodeTypeMap.#FIRST_OUT] || null;
881
770
  }
882
-
883
771
  lastIn(node) {
884
772
  return this.data[node + NodeTypeMap.#LAST_IN] || null;
885
773
  }
886
-
887
774
  lastOut(node) {
888
775
  return this.data[node + NodeTypeMap.#LAST_OUT] || null;
889
776
  }
890
-
891
777
  linkIn(node, edge) {
892
778
  let first = this.firstIn(node);
893
779
  let last = this.lastIn(node);
@@ -895,20 +781,16 @@ class NodeTypeMap extends SharedTypeMap {
895
781
  this.data[node + NodeTypeMap.#LAST_IN] = edge;
896
782
  return last;
897
783
  }
898
-
899
784
  unlinkIn(node, edge, prev, next) {
900
785
  let first = this.firstIn(node);
901
786
  let last = this.lastIn(node);
902
-
903
787
  if (last === edge) {
904
788
  this.data[node + NodeTypeMap.#LAST_IN] = prev === null ? 0 : prev;
905
789
  }
906
-
907
790
  if (first === edge) {
908
791
  this.data[node + NodeTypeMap.#FIRST_IN] = next === null ? 0 : next;
909
792
  }
910
793
  }
911
-
912
794
  linkOut(node, edge) {
913
795
  let first = this.firstOut(node);
914
796
  let last = this.lastOut(node);
@@ -916,29 +798,23 @@ class NodeTypeMap extends SharedTypeMap {
916
798
  this.data[node + NodeTypeMap.#LAST_OUT] = edge;
917
799
  return last;
918
800
  }
919
-
920
801
  unlinkOut(node, edge, prev, next) {
921
802
  let first = this.firstOut(node);
922
803
  let last = this.lastOut(node);
923
-
924
804
  if (last === edge) {
925
805
  this.data[node + NodeTypeMap.#LAST_OUT] = prev === null ? 0 : prev;
926
806
  }
927
-
928
807
  if (first === edge) {
929
808
  this.data[node + NodeTypeMap.#FIRST_OUT] = next === null ? 0 : next;
930
809
  }
931
810
  }
932
-
933
811
  }
812
+
934
813
  /**
935
814
  * Edges are stored in a `SharedTypeMap`,
936
815
  * keyed on the 'from' and 'to' node ids, and the edge type.
937
816
  */
938
-
939
-
940
817
  exports.NodeTypeMap = NodeTypeMap;
941
-
942
818
  class EdgeTypeMap extends SharedTypeMap {
943
819
  /**
944
820
  * In addition to the header defined by `SharedTypeMap`, the header for
@@ -956,8 +832,8 @@ class EdgeTypeMap extends SharedTypeMap {
956
832
  */
957
833
  static HEADER_SIZE = 3;
958
834
  /** The offset from the header where the delete count is stored. */
959
-
960
835
  static #DELETES = 2;
836
+
961
837
  /**
962
838
  * In addition to the item fields defined by `SharedTypeMap`,
963
839
  * each edge includes another 6 4-byte chunks:
@@ -977,106 +853,83 @@ class EdgeTypeMap extends SharedTypeMap {
977
853
  * │ NEXT │ TYPE │ FROM │ TO │ NEXT_IN │ PREV_IN │ NEXT_OUT │ PREV_OUT │
978
854
  * └──────┴──────┴──────┴────┴─────────┴─────────┴──────────┴──────────┘
979
855
  */
980
-
981
856
  static ITEM_SIZE = 8;
982
857
  /** The offset at which an edge's 'from' node id is stored. */
983
-
984
858
  static #FROM = 2;
985
859
  /** The offset at which an edge's 'to' node id is stored. */
986
-
987
860
  static #TO = 3;
988
861
  /** The offset at which the 'to' node's next incoming edge is stored. */
989
-
990
862
  static #NEXT_IN = 4;
991
863
  /** The offset at which the 'to' node's previous incoming edge is stored. */
992
-
993
864
  static #PREV_IN = 5;
994
865
  /** The offset at which the 'from' node's next outgoing edge is stored. */
995
-
996
866
  static #NEXT_OUT = 6;
997
867
  /** The offset at which the 'from' node's previous outgoing edge is stored. */
998
-
999
868
  static #PREV_OUT = 7;
1000
- /** The smallest functional edge map capacity. */
1001
869
 
870
+ /** The smallest functional edge map capacity. */
1002
871
  static MIN_CAPACITY = 2;
1003
872
  /** The largest possible edge map capacity. */
1004
-
1005
- static MAX_CAPACITY = Math.floor( // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length#what_went_wrong
873
+ static MAX_CAPACITY = Math.floor(
874
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length#what_went_wrong
1006
875
  (2 ** 31 - 1 - EdgeTypeMap.HEADER_SIZE) / EdgeTypeMap.ITEM_SIZE / EdgeTypeMap.BUCKET_SIZE);
1007
876
  /** The size after which to grow the capacity by the minimum factor. */
1008
-
1009
877
  static PEAK_CAPACITY = 2 ** 18;
1010
-
1011
878
  get deletes() {
1012
879
  return this.data[EdgeTypeMap.#DELETES];
1013
880
  }
1014
-
1015
881
  getNextAddress() {
1016
882
  let {
1017
883
  ITEM_SIZE
1018
884
  } = this.constructor;
1019
885
  return this.addressableLimit + (this.count + this.deletes) * ITEM_SIZE;
1020
886
  }
1021
-
1022
887
  add(hash, from, to, type) {
1023
- (0, _assert().default)(hash >= 0 && hash < this.capacity, `Invalid edge hash ${String(hash)}`); // Use the next available edge address.
1024
-
1025
- let edge = this.getNextAddress(); // Add our new edge to its hash bucket.
1026
-
888
+ (0, _assert().default)(hash >= 0 && hash < this.capacity, `Invalid edge hash ${String(hash)}`);
889
+ // Use the next available edge address.
890
+ let edge = this.getNextAddress();
891
+ // Add our new edge to its hash bucket.
1027
892
  this.link(hash, edge, type);
1028
893
  this.data[edge + EdgeTypeMap.#FROM] = (0, _types.fromNodeId)(from);
1029
894
  this.data[edge + EdgeTypeMap.#TO] = (0, _types.fromNodeId)(to);
1030
895
  return edge;
1031
896
  }
1032
-
1033
897
  delete(edge) {
1034
898
  this.data[edge + EdgeTypeMap.#FROM] = 0;
1035
899
  this.data[edge + EdgeTypeMap.#TO] = 0;
1036
900
  this.data[EdgeTypeMap.#DELETES]++;
1037
901
  }
1038
-
1039
902
  addressOf(hash, from, to, type) {
1040
903
  let address = this.head(hash);
1041
-
1042
904
  while (address !== null) {
1043
905
  if (this.typeOf(address) === type && this.from(address) === from && this.to(address) === to) {
1044
906
  return address;
1045
907
  }
1046
-
1047
908
  address = this.next(address);
1048
909
  }
1049
-
1050
910
  return null;
1051
911
  }
1052
-
1053
912
  from(edge) {
1054
913
  return (0, _types.toNodeId)(this.data[edge + EdgeTypeMap.#FROM]);
1055
914
  }
1056
-
1057
915
  to(edge) {
1058
916
  return (0, _types.toNodeId)(this.data[edge + EdgeTypeMap.#TO]);
1059
917
  }
1060
-
1061
918
  nextIn(edge) {
1062
919
  return this.data[edge + EdgeTypeMap.#NEXT_IN] || null;
1063
920
  }
1064
-
1065
921
  prevIn(edge) {
1066
922
  return this.data[edge + EdgeTypeMap.#PREV_IN] || null;
1067
923
  }
1068
-
1069
924
  linkIn(edge, next) {
1070
925
  this.data[edge + EdgeTypeMap.#NEXT_IN] = next;
1071
926
  this.data[next + EdgeTypeMap.#PREV_IN] = edge;
1072
927
  }
1073
-
1074
928
  unlinkIn(edge) {
1075
929
  let next = this.nextIn(edge);
1076
930
  let prev = this.prevIn(edge);
1077
931
  this.data[edge + EdgeTypeMap.#NEXT_IN] = 0;
1078
932
  this.data[edge + EdgeTypeMap.#PREV_IN] = 0;
1079
-
1080
933
  if (next !== null && prev !== null) {
1081
934
  this.data[prev + EdgeTypeMap.#NEXT_IN] = next;
1082
935
  this.data[next + EdgeTypeMap.#PREV_IN] = prev;
@@ -1086,26 +939,21 @@ class EdgeTypeMap extends SharedTypeMap {
1086
939
  this.data[prev + EdgeTypeMap.#NEXT_IN] = 0;
1087
940
  }
1088
941
  }
1089
-
1090
942
  nextOut(edge) {
1091
943
  return this.data[edge + EdgeTypeMap.#NEXT_OUT] || null;
1092
944
  }
1093
-
1094
945
  prevOut(edge) {
1095
946
  return this.data[edge + EdgeTypeMap.#PREV_OUT] || null;
1096
947
  }
1097
-
1098
948
  linkOut(edge, next) {
1099
949
  this.data[edge + EdgeTypeMap.#NEXT_OUT] = next;
1100
950
  this.data[next + EdgeTypeMap.#PREV_OUT] = edge;
1101
951
  }
1102
-
1103
952
  unlinkOut(edge) {
1104
953
  let next = this.nextOut(edge);
1105
954
  let prev = this.prevOut(edge);
1106
955
  this.data[edge + EdgeTypeMap.#NEXT_OUT] = 0;
1107
956
  this.data[edge + EdgeTypeMap.#PREV_OUT] = 0;
1108
-
1109
957
  if (next !== null && prev !== null) {
1110
958
  this.data[prev + EdgeTypeMap.#NEXT_OUT] = next;
1111
959
  this.data[next + EdgeTypeMap.#PREV_OUT] = prev;
@@ -1115,9 +963,8 @@ class EdgeTypeMap extends SharedTypeMap {
1115
963
  this.data[prev + EdgeTypeMap.#NEXT_OUT] = 0;
1116
964
  }
1117
965
  }
1118
- /** Create a hash of the edge connecting the `from` and `to` nodes. */
1119
-
1120
966
 
967
+ /** Create a hash of the edge connecting the `from` and `to` nodes. */
1121
968
  hash(from, to, type) {
1122
969
  // Each parameter is hashed by mixing its upper bits into its lower bits to
1123
970
  // increase the likelihood that a change to any bit of the input will vary
@@ -1126,33 +973,27 @@ class EdgeTypeMap extends SharedTypeMap {
1126
973
  let hash = 17;
1127
974
  hash = hash * 37 + hash32shift(from);
1128
975
  hash = hash * 37 + hash32shift(to);
1129
- hash = hash * 37 + hash32shift(type); // Finally, we map the hash to a value modulo the edge capacity.
1130
-
976
+ hash = hash * 37 + hash32shift(type);
977
+ // Finally, we map the hash to a value modulo the edge capacity.
1131
978
  hash %= this.capacity;
1132
979
  return hash;
1133
980
  }
981
+ }
1134
982
 
1135
- } // From https://gist.github.com/badboy/6267743#32-bit-mix-functions
1136
-
1137
-
983
+ // From https://gist.github.com/badboy/6267743#32-bit-mix-functions
1138
984
  exports.EdgeTypeMap = EdgeTypeMap;
1139
-
1140
985
  function hash32shift(key) {
1141
986
  key = ~key + (key << 15); // key = (key << 15) - key - 1;
1142
-
1143
987
  key = key ^ key >> 12;
1144
988
  key = key + (key << 2);
1145
989
  key = key ^ key >> 4;
1146
990
  key = key * 2057; // key = (key + (key << 3)) + (key << 11);
1147
-
1148
991
  key = key ^ key >> 16;
1149
992
  return key;
1150
993
  }
1151
-
1152
994
  function interpolate(x, y, t) {
1153
995
  return x + (y - x) * Math.min(1, Math.max(0, t));
1154
996
  }
1155
-
1156
997
  function increaseNodeCapacity(nodeCapacity) {
1157
998
  let {
1158
999
  MIN_CAPACITY,
@@ -1162,7 +1003,6 @@ function increaseNodeCapacity(nodeCapacity) {
1162
1003
  (0, _assert().default)(newCapacity <= MAX_CAPACITY, 'Node capacity overflow!');
1163
1004
  return Math.max(MIN_CAPACITY, newCapacity);
1164
1005
  }
1165
-
1166
1006
  function getNextEdgeCapacity(capacity, count, load) {
1167
1007
  let {
1168
1008
  MIN_CAPACITY,
@@ -1170,12 +1010,12 @@ function getNextEdgeCapacity(capacity, count, load) {
1170
1010
  PEAK_CAPACITY
1171
1011
  } = EdgeTypeMap;
1172
1012
  let newCapacity = capacity;
1173
-
1174
1013
  if (load > LOAD_FACTOR) {
1175
1014
  // This is intended to strike a balance between growing the edge capacity
1176
1015
  // in too small increments, which causes a lot of resizing, and growing
1177
1016
  // the edge capacity in too large increments, which results in a lot of
1178
1017
  // wasted memory.
1018
+
1179
1019
  let growFactor = interpolate(MAX_GROW_FACTOR, MIN_GROW_FACTOR, capacity / PEAK_CAPACITY);
1180
1020
  newCapacity = Math.round(capacity * growFactor);
1181
1021
  } else if (load < UNLOAD_FACTOR) {
@@ -1183,7 +1023,6 @@ function getNextEdgeCapacity(capacity, count, load) {
1183
1023
  // but this is only likely to occur when a lot of edges have been removed.
1184
1024
  newCapacity = Math.round(capacity * SHRINK_FACTOR);
1185
1025
  }
1186
-
1187
1026
  (0, _assert().default)(newCapacity <= MAX_CAPACITY, 'Edge capacity overflow!');
1188
1027
  return Math.max(MIN_CAPACITY, newCapacity);
1189
1028
  }