mirror of
https://github.com/denoland/std.git
synced 2024-11-21 20:50:22 +00:00
fix(semver): throw on invalid input in parseRange()
(#5567)
* fix(semver): throw on invalid input in `parseRange()` * fix * fix * fix
This commit is contained in:
parent
b064ee1212
commit
3a446538b1
@ -57,14 +57,6 @@ export const ALL: Comparator = {
|
||||
...ANY,
|
||||
};
|
||||
|
||||
/**
|
||||
* A comparator which will not span any semantic versions
|
||||
*/
|
||||
export const NONE: Comparator = {
|
||||
operator: "<",
|
||||
...MIN,
|
||||
};
|
||||
|
||||
export const OPERATORS = [
|
||||
undefined,
|
||||
"=",
|
||||
|
@ -2,7 +2,7 @@
|
||||
// This module is browser compatible.
|
||||
import type { Comparator, Range } from "./types.ts";
|
||||
import { OPERATORS } from "./_constants.ts";
|
||||
import { ALL, NONE } from "./_constants.ts";
|
||||
import { ALL } from "./_constants.ts";
|
||||
import { isSemVer } from "./is_semver.ts";
|
||||
|
||||
function isComparator(value: unknown): value is Comparator {
|
||||
@ -10,7 +10,7 @@ function isComparator(value: unknown): value is Comparator {
|
||||
value === null || value === undefined || Array.isArray(value) ||
|
||||
typeof value !== "object"
|
||||
) return false;
|
||||
if (value === NONE || value === ALL) return true;
|
||||
if (value === ALL) return true;
|
||||
const { operator } = value as Comparator;
|
||||
return (
|
||||
(operator === undefined ||
|
||||
|
@ -4,7 +4,6 @@ import { assertEquals } from "@std/assert";
|
||||
import { parse } from "./parse.ts";
|
||||
import { parseRange } from "./parse_range.ts";
|
||||
import { maxSatisfying } from "./max_satisfying.ts";
|
||||
import { MAX, MIN } from "./_constants.ts";
|
||||
|
||||
Deno.test({
|
||||
name: "maxSatisfying()",
|
||||
@ -26,8 +25,3 @@ Deno.test({
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test("minSatisfying() handles bad ranges", function () {
|
||||
const r = parseRange("some frogs and sneks-v2.5.6");
|
||||
assertEquals(maxSatisfying([MIN, MAX], r), undefined);
|
||||
});
|
||||
|
@ -4,7 +4,6 @@ import { assertEquals } from "@std/assert";
|
||||
import { parse } from "./parse.ts";
|
||||
import { parseRange } from "./parse_range.ts";
|
||||
import { minSatisfying } from "./min_satisfying.ts";
|
||||
import { MAX, MIN } from "./_constants.ts";
|
||||
|
||||
Deno.test("minSatisfying()", async (t) => {
|
||||
const versions: [string[], string, string][] = [
|
||||
@ -23,8 +22,3 @@ Deno.test("minSatisfying()", async (t) => {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Deno.test("minSatisfying() handles bad ranges", function () {
|
||||
const r = parseRange("some frogs and sneks-v2.5.6");
|
||||
assertEquals(minSatisfying([MIN, MAX], r), undefined);
|
||||
});
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
parsePrerelease,
|
||||
XRANGE,
|
||||
} from "./_shared.ts";
|
||||
import { ALL, ANY, NONE } from "./_constants.ts";
|
||||
import { ALL, ANY } from "./_constants.ts";
|
||||
import type { Comparator, Operator, Range } from "./types.ts";
|
||||
|
||||
type ComparatorRegExpGroup = {
|
||||
@ -21,11 +21,11 @@ type ComparatorRegExpGroup = {
|
||||
buildmetadata: string;
|
||||
};
|
||||
|
||||
function parseComparator(comparator: string): Comparator {
|
||||
function parseComparator(comparator: string): Comparator | null {
|
||||
const match = comparator.match(COMPARATOR_REGEXP);
|
||||
const groups = match?.groups;
|
||||
|
||||
if (!groups) return NONE;
|
||||
if (!groups) return null;
|
||||
|
||||
const { operator, prerelease, buildmetadata } =
|
||||
groups as ComparatorRegExpGroup;
|
||||
@ -349,7 +349,7 @@ function handleEqualOperator(groups: RangeRegExpGroups): Comparator[] {
|
||||
return [{ operator: undefined, major, minor, patch, prerelease, build }];
|
||||
}
|
||||
|
||||
function parseOperatorRange(string: string): Comparator | Comparator[] {
|
||||
function parseOperatorRange(string: string): Comparator | Comparator[] | null {
|
||||
const groups = string.match(OPERATOR_XRANGE_REGEXP)
|
||||
?.groups as RangeRegExpGroups;
|
||||
if (!groups) return parseComparator(string);
|
||||
@ -375,7 +375,7 @@ function parseOperatorRange(string: string): Comparator | Comparator[] {
|
||||
throw new Error(`'${groups.operator}' is not a valid operator.`);
|
||||
}
|
||||
}
|
||||
function parseOperatorRanges(string: string): Comparator[] {
|
||||
function parseOperatorRanges(string: string): (Comparator | null)[] {
|
||||
return string.split(/\s+/).flatMap(parseOperatorRange);
|
||||
}
|
||||
|
||||
@ -404,9 +404,13 @@ function parseOperatorRanges(string: string): Comparator[] {
|
||||
* @returns A valid SemVer range
|
||||
*/
|
||||
export function parseRange(range: string): Range {
|
||||
return range
|
||||
const result = range
|
||||
// remove spaces between operators and versions
|
||||
.replaceAll(/(?<=<|>|=|~) +/g, "")
|
||||
.replaceAll(/(?<=<|>|=|~|\^)(\s+)/g, "")
|
||||
.split(/\s*\|\|\s*/)
|
||||
.map((string) => parseHyphenRange(string) || parseOperatorRanges(string));
|
||||
if (result.some((r) => r.includes(null))) {
|
||||
throw new TypeError(`Invalid range: ${range}`);
|
||||
}
|
||||
return result as Range;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright Isaac Z. Schlueter and Contributors. All rights reserved. ISC license.
|
||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
import { assertEquals } from "@std/assert";
|
||||
import { assertEquals, assertThrows } from "@std/assert";
|
||||
import { parseRange } from "./parse_range.ts";
|
||||
import type { Range } from "./types.ts";
|
||||
|
||||
@ -351,18 +351,6 @@ Deno.test("parseRange() parse ranges of different kinds", () => {
|
||||
{ operator: "<", major: 0, minor: 0, patch: 2 },
|
||||
],
|
||||
]],
|
||||
["blerg", [
|
||||
[
|
||||
{
|
||||
operator: "<",
|
||||
major: 0,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
prerelease: [],
|
||||
build: [],
|
||||
},
|
||||
],
|
||||
]],
|
||||
["^1.2.3", [
|
||||
[
|
||||
{ operator: ">=", major: 1, minor: 2, patch: 3, prerelease: [] },
|
||||
@ -591,6 +579,12 @@ Deno.test("parseRange() parses ranges with caret", () => {
|
||||
{ operator: "<", major: 2, minor: 0, patch: 0 },
|
||||
],
|
||||
]],
|
||||
["^ 1.2.3", [
|
||||
[
|
||||
{ operator: ">=", major: 1, minor: 2, patch: 3, prerelease: [] },
|
||||
{ operator: "<", major: 2, minor: 0, patch: 0 },
|
||||
],
|
||||
]],
|
||||
["^0.2.3", [
|
||||
[
|
||||
{ operator: ">=", major: 0, minor: 2, patch: 3, prerelease: [] },
|
||||
@ -664,3 +658,7 @@ Deno.test("parseRange() parses ranges with caret", () => {
|
||||
assertEquals(range, expected);
|
||||
}
|
||||
});
|
||||
|
||||
Deno.test("parseRange() throws on invalid range", () => {
|
||||
assertThrows(() => parseRange("blerg"), TypeError, "Invalid range: blerg");
|
||||
});
|
||||
|
@ -269,7 +269,6 @@ Deno.test({
|
||||
["<=1.2.3", "1.2.3-beta"],
|
||||
|
||||
// invalid ranges never satisfied!
|
||||
["blerg", "1.2.3"],
|
||||
["^1.2.3", "2.0.0-pre"],
|
||||
|
||||
["1.0.0 - 2.0.0", "0.0.0"],
|
||||
|
Loading…
Reference in New Issue
Block a user