@vltpkg/semver 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +48 -3
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -15,6 +15,20 @@ export const parse = (version) => {
|
|
|
15
15
|
return undefined;
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
* Bounded cache for {@link parseRange}, keyed on `(includePrerelease, raw)`.
|
|
20
|
+
* `Range` is effectively immutable after construction, so parsed results
|
|
21
|
+
* (including `undefined` for invalid input, tracked via `has()`) are safe
|
|
22
|
+
* to share across callers. Cleared wholesale once it hits the cap rather
|
|
23
|
+
* than tracking LRU order, since real workloads only see a few hundred to
|
|
24
|
+
* a few thousand distinct range strings per install.
|
|
25
|
+
*
|
|
26
|
+
* Sharing instances also means textually identical ranges are identical
|
|
27
|
+
* objects, which is what makes the identity-keyed `intersectsCache` below
|
|
28
|
+
* effective.
|
|
29
|
+
*/
|
|
30
|
+
const rangeCache = new Map();
|
|
31
|
+
const MAX_RANGE_CACHE = 4096;
|
|
18
32
|
/** Return the parsed version range, or `undefined` if invalid */
|
|
19
33
|
export const parseRange = (range, includePrerelease = false) => {
|
|
20
34
|
if (typeof range === 'object') {
|
|
@@ -22,12 +36,23 @@ export const parseRange = (range, includePrerelease = false) => {
|
|
|
22
36
|
return range;
|
|
23
37
|
range = range.raw;
|
|
24
38
|
}
|
|
39
|
+
const key = `${+includePrerelease}\0${range}`;
|
|
40
|
+
// single map lookup on the common hit path; the extra has() check only
|
|
41
|
+
// runs for ranges cached as invalid (undefined) and for misses
|
|
42
|
+
const cached = rangeCache.get(key);
|
|
43
|
+
if (cached !== undefined || rangeCache.has(key))
|
|
44
|
+
return cached;
|
|
45
|
+
let parsed;
|
|
25
46
|
try {
|
|
26
|
-
|
|
47
|
+
parsed = new Range(range, includePrerelease);
|
|
27
48
|
}
|
|
28
49
|
catch {
|
|
29
|
-
|
|
50
|
+
parsed = undefined;
|
|
30
51
|
}
|
|
52
|
+
if (rangeCache.size >= MAX_RANGE_CACHE)
|
|
53
|
+
rangeCache.clear();
|
|
54
|
+
rangeCache.set(key, parsed);
|
|
55
|
+
return parsed;
|
|
31
56
|
};
|
|
32
57
|
/**
|
|
33
58
|
* return true if the version is valid
|
|
@@ -348,6 +373,16 @@ export const stable = (versions) => versions.filter(v => {
|
|
|
348
373
|
return false;
|
|
349
374
|
return !p.prerelease?.length;
|
|
350
375
|
});
|
|
376
|
+
/**
|
|
377
|
+
* Identity-keyed cache for {@link intersects}. Keying on the `Range`
|
|
378
|
+
* instances themselves (rather than a string of their raw sources) keeps
|
|
379
|
+
* the hit path free of string building, and needs no size cap or clear
|
|
380
|
+
* policy: entries are dropped by GC together with their ranges. It relies
|
|
381
|
+
* on `rangeCache` deduping instances, so string inputs and `spec.range`
|
|
382
|
+
* objects for the same source share entries; callers constructing a fresh
|
|
383
|
+
* `Range` per call simply recompute, as they did before memoization.
|
|
384
|
+
*/
|
|
385
|
+
const intersectsCache = new WeakMap();
|
|
351
386
|
/**
|
|
352
387
|
* Return true if the range r1 intersects any of the ranges r2
|
|
353
388
|
* r1 and r2 are either Range objects or range strings.
|
|
@@ -361,8 +396,18 @@ export const intersects = (r1, r2, includePrerelease) => {
|
|
|
361
396
|
// If either range is 'any', they intersect
|
|
362
397
|
if (range1.isAny || range2.isAny)
|
|
363
398
|
return true;
|
|
399
|
+
let inner = intersectsCache.get(range1);
|
|
400
|
+
const cached = inner?.get(range2);
|
|
401
|
+
if (cached !== undefined)
|
|
402
|
+
return cached;
|
|
364
403
|
// Check if any set from range1 intersects with any set from range2
|
|
365
|
-
|
|
404
|
+
const result = range1.set.some(set1 => range2.set.some(set2 => intersectComparators(set1, set2)));
|
|
405
|
+
if (!inner) {
|
|
406
|
+
inner = new WeakMap();
|
|
407
|
+
intersectsCache.set(range1, inner);
|
|
408
|
+
}
|
|
409
|
+
inner.set(range2, result);
|
|
410
|
+
return result;
|
|
366
411
|
};
|
|
367
412
|
/**
|
|
368
413
|
* Check if range r1 is a subset of range r2.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vltpkg/semver",
|
|
3
3
|
"description": "The semantic version parser used by vlt",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.3",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/vltpkg/vltpkg.git",
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
"url": "http://vlt.sh"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@vltpkg/error-cause": "1.0.
|
|
17
|
-
"@vltpkg/fast-split": "1.0.
|
|
18
|
-
"@vltpkg/types": "1.0.
|
|
16
|
+
"@vltpkg/error-cause": "1.0.3",
|
|
17
|
+
"@vltpkg/fast-split": "1.0.3",
|
|
18
|
+
"@vltpkg/types": "1.0.3"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@eslint/js": "^9.39.1",
|