aboutsummaryrefslogtreecommitdiff
path: root/node_modules/fbjs/lib/VersionRange.js.flow
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-05-03 15:35:00 +0200
committerFlorian Dold <florian.dold@gmail.com>2017-05-03 15:35:00 +0200
commitde98e0b232509d5f40c135d540a70e415272ff85 (patch)
treea79222a5b58484ab3b80d18efcaaa7ccc4769b33 /node_modules/fbjs/lib/VersionRange.js.flow
parente0c9d480a73fa629c1e4a47d3e721f1d2d345406 (diff)
node_modules
Diffstat (limited to 'node_modules/fbjs/lib/VersionRange.js.flow')
-rw-r--r--node_modules/fbjs/lib/VersionRange.js.flow373
1 files changed, 373 insertions, 0 deletions
diff --git a/node_modules/fbjs/lib/VersionRange.js.flow b/node_modules/fbjs/lib/VersionRange.js.flow
new file mode 100644
index 000000000..6aa27ed47
--- /dev/null
+++ b/node_modules/fbjs/lib/VersionRange.js.flow
@@ -0,0 +1,373 @@
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule VersionRange
+ */
+
+'use strict';
+
+const invariant = require('./invariant');
+
+const componentRegex = /\./;
+const orRegex = /\|\|/;
+const rangeRegex = /\s+\-\s+/;
+const modifierRegex = /^(<=|<|=|>=|~>|~|>|)?\s*(.+)/;
+const numericRegex = /^(\d*)(.*)/;
+
+/**
+ * Splits input `range` on "||" and returns true if any subrange matches
+ * `version`.
+ *
+ * @param {string} range
+ * @param {string} version
+ * @returns {boolean}
+ */
+function checkOrExpression(range, version) {
+ const expressions = range.split(orRegex);
+
+ if (expressions.length > 1) {
+ return expressions.some(range => VersionRange.contains(range, version));
+ } else {
+ range = expressions[0].trim();
+ return checkRangeExpression(range, version);
+ }
+}
+
+/**
+ * Splits input `range` on " - " (the surrounding whitespace is required) and
+ * returns true if version falls between the two operands.
+ *
+ * @param {string} range
+ * @param {string} version
+ * @returns {boolean}
+ */
+function checkRangeExpression(range, version) {
+ const expressions = range.split(rangeRegex);
+
+ invariant(expressions.length > 0 && expressions.length <= 2, 'the "-" operator expects exactly 2 operands');
+
+ if (expressions.length === 1) {
+ return checkSimpleExpression(expressions[0], version);
+ } else {
+ const [startVersion, endVersion] = expressions;
+ invariant(isSimpleVersion(startVersion) && isSimpleVersion(endVersion), 'operands to the "-" operator must be simple (no modifiers)');
+
+ return checkSimpleExpression('>=' + startVersion, version) && checkSimpleExpression('<=' + endVersion, version);
+ }
+}
+
+/**
+ * Checks if `range` matches `version`. `range` should be a "simple" range (ie.
+ * not a compound range using the " - " or "||" operators).
+ *
+ * @param {string} range
+ * @param {string} version
+ * @returns {boolean}
+ */
+function checkSimpleExpression(range, version) {
+ range = range.trim();
+ if (range === '') {
+ return true;
+ }
+
+ const versionComponents = version.split(componentRegex);
+ const { modifier, rangeComponents } = getModifierAndComponents(range);
+ switch (modifier) {
+ case '<':
+ return checkLessThan(versionComponents, rangeComponents);
+ case '<=':
+ return checkLessThanOrEqual(versionComponents, rangeComponents);
+ case '>=':
+ return checkGreaterThanOrEqual(versionComponents, rangeComponents);
+ case '>':
+ return checkGreaterThan(versionComponents, rangeComponents);
+ case '~':
+ case '~>':
+ return checkApproximateVersion(versionComponents, rangeComponents);
+ default:
+ return checkEqual(versionComponents, rangeComponents);
+ }
+}
+
+/**
+ * Checks whether `a` is less than `b`.
+ *
+ * @param {array<string>} a
+ * @param {array<string>} b
+ * @returns {boolean}
+ */
+function checkLessThan(a, b) {
+ return compareComponents(a, b) === -1;
+}
+
+/**
+ * Checks whether `a` is less than or equal to `b`.
+ *
+ * @param {array<string>} a
+ * @param {array<string>} b
+ * @returns {boolean}
+ */
+function checkLessThanOrEqual(a, b) {
+ const result = compareComponents(a, b);
+ return result === -1 || result === 0;
+}
+
+/**
+ * Checks whether `a` is equal to `b`.
+ *
+ * @param {array<string>} a
+ * @param {array<string>} b
+ * @returns {boolean}
+ */
+function checkEqual(a, b) {
+ return compareComponents(a, b) === 0;
+}
+
+/**
+ * Checks whether `a` is greater than or equal to `b`.
+ *
+ * @param {array<string>} a
+ * @param {array<string>} b
+ * @returns {boolean}
+ */
+function checkGreaterThanOrEqual(a, b) {
+ const result = compareComponents(a, b);
+ return result === 1 || result === 0;
+}
+
+/**
+ * Checks whether `a` is greater than `b`.
+ *
+ * @param {array<string>} a
+ * @param {array<string>} b
+ * @returns {boolean}
+ */
+function checkGreaterThan(a, b) {
+ return compareComponents(a, b) === 1;
+}
+
+/**
+ * Checks whether `a` is "reasonably close" to `b` (as described in
+ * https://www.npmjs.org/doc/misc/semver.html). For example, if `b` is "1.3.1"
+ * then "reasonably close" is defined as ">= 1.3.1 and < 1.4".
+ *
+ * @param {array<string>} a
+ * @param {array<string>} b
+ * @returns {boolean}
+ */
+function checkApproximateVersion(a, b) {
+ const lowerBound = b.slice();
+ const upperBound = b.slice();
+
+ if (upperBound.length > 1) {
+ upperBound.pop();
+ }
+ const lastIndex = upperBound.length - 1;
+ const numeric = parseInt(upperBound[lastIndex], 10);
+ if (isNumber(numeric)) {
+ upperBound[lastIndex] = numeric + 1 + '';
+ }
+
+ return checkGreaterThanOrEqual(a, lowerBound) && checkLessThan(a, upperBound);
+}
+
+/**
+ * Extracts the optional modifier (<, <=, =, >=, >, ~, ~>) and version
+ * components from `range`.
+ *
+ * For example, given `range` ">= 1.2.3" returns an object with a `modifier` of
+ * `">="` and `components` of `[1, 2, 3]`.
+ *
+ * @param {string} range
+ * @returns {object}
+ */
+function getModifierAndComponents(range) {
+ const rangeComponents = range.split(componentRegex);
+ const matches = rangeComponents[0].match(modifierRegex);
+ invariant(matches, 'expected regex to match but it did not');
+
+ return {
+ modifier: matches[1],
+ rangeComponents: [matches[2]].concat(rangeComponents.slice(1))
+ };
+}
+
+/**
+ * Determines if `number` is a number.
+ *
+ * @param {mixed} number
+ * @returns {boolean}
+ */
+function isNumber(number) {
+ return !isNaN(number) && isFinite(number);
+}
+
+/**
+ * Tests whether `range` is a "simple" version number without any modifiers
+ * (">", "~" etc).
+ *
+ * @param {string} range
+ * @returns {boolean}
+ */
+function isSimpleVersion(range) {
+ return !getModifierAndComponents(range).modifier;
+}
+
+/**
+ * Zero-pads array `array` until it is at least `length` long.
+ *
+ * @param {array} array
+ * @param {number} length
+ */
+function zeroPad(array, length) {
+ for (let i = array.length; i < length; i++) {
+ array[i] = '0';
+ }
+}
+
+/**
+ * Normalizes `a` and `b` in preparation for comparison by doing the following:
+ *
+ * - zero-pads `a` and `b`
+ * - marks any "x", "X" or "*" component in `b` as equivalent by zero-ing it out
+ * in both `a` and `b`
+ * - marks any final "*" component in `b` as a greedy wildcard by zero-ing it
+ * and all of its successors in `a`
+ *
+ * @param {array<string>} a
+ * @param {array<string>} b
+ * @returns {array<array<string>>}
+ */
+function normalizeVersions(a, b) {
+ a = a.slice();
+ b = b.slice();
+
+ zeroPad(a, b.length);
+
+ // mark "x" and "*" components as equal
+ for (let i = 0; i < b.length; i++) {
+ const matches = b[i].match(/^[x*]$/i);
+ if (matches) {
+ b[i] = a[i] = '0';
+
+ // final "*" greedily zeros all remaining components
+ if (matches[0] === '*' && i === b.length - 1) {
+ for (let j = i; j < a.length; j++) {
+ a[j] = '0';
+ }
+ }
+ }
+ }
+
+ zeroPad(b, a.length);
+
+ return [a, b];
+}
+
+/**
+ * Returns the numerical -- not the lexicographical -- ordering of `a` and `b`.
+ *
+ * For example, `10-alpha` is greater than `2-beta`.
+ *
+ * @param {string} a
+ * @param {string} b
+ * @returns {number} -1, 0 or 1 to indicate whether `a` is less than, equal to,
+ * or greater than `b`, respectively
+ */
+function compareNumeric(a, b) {
+ const aPrefix = a.match(numericRegex)[1];
+ const bPrefix = b.match(numericRegex)[1];
+ const aNumeric = parseInt(aPrefix, 10);
+ const bNumeric = parseInt(bPrefix, 10);
+
+ if (isNumber(aNumeric) && isNumber(bNumeric) && aNumeric !== bNumeric) {
+ return compare(aNumeric, bNumeric);
+ } else {
+ return compare(a, b);
+ }
+}
+
+/**
+ * Returns the ordering of `a` and `b`.
+ *
+ * @param {string|number} a
+ * @param {string|number} b
+ * @returns {number} -1, 0 or 1 to indicate whether `a` is less than, equal to,
+ * or greater than `b`, respectively
+ */
+function compare(a, b) {
+ invariant(typeof a === typeof b, '"a" and "b" must be of the same type');
+
+ if (a > b) {
+ return 1;
+ } else if (a < b) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+/**
+ * Compares arrays of version components.
+ *
+ * @param {array<string>} a
+ * @param {array<string>} b
+ * @returns {number} -1, 0 or 1 to indicate whether `a` is less than, equal to,
+ * or greater than `b`, respectively
+ */
+function compareComponents(a, b) {
+ const [aNormalized, bNormalized] = normalizeVersions(a, b);
+
+ for (let i = 0; i < bNormalized.length; i++) {
+ const result = compareNumeric(aNormalized[i], bNormalized[i]);
+ if (result) {
+ return result;
+ }
+ }
+
+ return 0;
+}
+
+var VersionRange = {
+ /**
+ * Checks whether `version` satisfies the `range` specification.
+ *
+ * We support a subset of the expressions defined in
+ * https://www.npmjs.org/doc/misc/semver.html:
+ *
+ * version Must match version exactly
+ * =version Same as just version
+ * >version Must be greater than version
+ * >=version Must be greater than or equal to version
+ * <version Must be less than version
+ * <=version Must be less than or equal to version
+ * ~version Must be at least version, but less than the next significant
+ * revision above version:
+ * "~1.2.3" is equivalent to ">= 1.2.3 and < 1.3"
+ * ~>version Equivalent to ~version
+ * 1.2.x Must match "1.2.x", where "x" is a wildcard that matches
+ * anything
+ * 1.2.* Similar to "1.2.x", but "*" in the trailing position is a
+ * "greedy" wildcard, so will match any number of additional
+ * components:
+ * "1.2.*" will match "1.2.1", "1.2.1.1", "1.2.1.1.1" etc
+ * * Any version
+ * "" (Empty string) Same as *
+ * v1 - v2 Equivalent to ">= v1 and <= v2"
+ * r1 || r2 Passes if either r1 or r2 are satisfied
+ *
+ * @param {string} range
+ * @param {string} version
+ * @returns {boolean}
+ */
+ contains(range, version) {
+ return checkOrExpression(range.trim(), version.trim());
+ }
+};
+
+module.exports = VersionRange; \ No newline at end of file