From 9c8cac4a2e701ec99edcdf6ad6c12bb6102b0102 Mon Sep 17 00:00:00 2001 From: Cassidy Marble Date: Tue, 6 Oct 2026 18:01:38 -0300 Subject: [PATCH] [Perf] `nvm_is_valid_version`, `nvm_validate_implicit_alias`: avoid forks --- nvm.sh | 30 +++++++++-------------- test/fast/Unit tests/nvm_is_valid_version | 19 ++++++++++++++ 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/nvm.sh b/nvm.sh index 20d880ad..a1df0506 100755 --- a/nvm.sh +++ b/nvm.sh @@ -1061,17 +1061,14 @@ ${NVM_LS_REMOTE_POST_MERGED_OUTPUT}" | nvm_grep -v "N/A" | command sed '/^ *$/d' } nvm_is_valid_version() { - if nvm_validate_implicit_alias "${1-}" 2>/dev/null; then - return 0 - fi case "${1-}" in - "$(nvm_iojs_prefix)" | \ - "$(nvm_node_prefix)") + "stable" | "unstable" | "iojs" | "node") return 0 ;; *) local VERSION - VERSION="$(nvm_strip_iojs_prefix "${1-}")" + VERSION="${1-}" + VERSION="${VERSION#iojs-}" local NVM_VERSION_CORE NVM_VERSION_CORE="${VERSION#v}" case "${NVM_VERSION_CORE}" in @@ -1085,6 +1082,9 @@ nvm_is_valid_version() { *.*.*) ;; *) return 1 ;; esac + # a prerelease's `-` makes it unreachable for the pure-shell checks + # below, so do the full check now. + nvm_version_greater_than_or_equal_to "${VERSION}" 0 || return 1 ;; *.) NVM_VERSION_CORE="${NVM_VERSION_CORE%.}" @@ -1093,7 +1093,7 @@ nvm_is_valid_version() { case "${NVM_VERSION_CORE}" in '' | .* | *. | *..* | *.*.*.* | *[!0-9.]*) return 1 ;; esac - nvm_version_greater_than_or_equal_to "${VERSION}" 0 + # every version that reaches this point is a number, and so `>= 0` ;; esac } @@ -1741,12 +1741,9 @@ nvm_add_iojs_prefix() { } nvm_strip_iojs_prefix() { - local NVM_IOJS_PREFIX - NVM_IOJS_PREFIX="$(nvm_iojs_prefix)" - case "${1-}" in - "${NVM_IOJS_PREFIX}") nvm_echo ;; - *) nvm_echo "${1#"${NVM_IOJS_PREFIX}"-}" ;; + "iojs") nvm_echo ;; + *) nvm_echo "${1#iojs-}" ;; esac } @@ -2470,17 +2467,12 @@ BEGIN { } nvm_validate_implicit_alias() { - local NVM_IOJS_PREFIX - NVM_IOJS_PREFIX="$(nvm_iojs_prefix)" - local NVM_NODE_PREFIX - NVM_NODE_PREFIX="$(nvm_node_prefix)" - case "$1" in - "stable" | "unstable" | "${NVM_IOJS_PREFIX}" | "${NVM_NODE_PREFIX}") + "stable" | "unstable" | "iojs" | "node") return ;; *) - nvm_err "Only implicit aliases 'stable', 'unstable', '${NVM_IOJS_PREFIX}', and '${NVM_NODE_PREFIX}' are supported." + nvm_err "Only implicit aliases 'stable', 'unstable', 'iojs', and 'node' are supported." return 1 ;; esac diff --git a/test/fast/Unit tests/nvm_is_valid_version b/test/fast/Unit tests/nvm_is_valid_version index 8b03d14c..806b4fb3 100755 --- a/test/fast/Unit tests/nvm_is_valid_version +++ b/test/fast/Unit tests/nvm_is_valid_version @@ -41,3 +41,22 @@ nvm_is_valid_version v9.9.1-nightly201803256591d9f761 || die "nvm_is_valid_versi nvm_is_valid_version v9.0.0-v8-canary201710301f8f3dcf36 || die "nvm_is_valid_version v9.0.0-v8-canary201710301f8f3dcf36 did not return 0" nvm_is_valid_version v8.16.2-test201910293843c56739f || die "nvm_is_valid_version v8.16.2-test201910293843c56739f did not return 0" nvm_is_valid_version iojs-v3.2.1-nightly201508291a531b4e44 || die "nvm_is_valid_version iojs-v3.2.1-nightly201508291a531b4e44 did not return 0" + +# `nvm_is_valid_version` must not fork a command for a plain version: mock +# `awk`, which the version comparisons used, and fail if it runs. (Prereleases +# still reach the comparison, which is why this checks a release version.) +TEST_DIR="$(pwd)/nvm_is_valid_version_tmp" +[ ! -e "${TEST_DIR}" ] && mkdir "${TEST_DIR}" +MOCK_BIN="${TEST_DIR}/bin" +mkdir -p "${MOCK_BIN}" +{ + echo '#!/bin/sh' + echo 'echo "awk was called" >&2' + echo 'exit 1' +} > "${MOCK_BIN}/awk" +chmod +x "${MOCK_BIN}/awk" + +PATH="${MOCK_BIN}:${PATH}" nvm_is_valid_version v18.20.0 \ + || die 'nvm_is_valid_version v18.20.0 forked a command' + +rm -rf "${TEST_DIR}"