diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2024-04-30 23:41:29 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-30 23:41:29 -0400 |
commit | 56bf634fa9721832b605dd91ced5329e0329a8f8 (patch) | |
tree | 15595d6beca6d712ad502c830c42fe533c25c237 | |
parent | 486437fee1ac53610a901b07bda91909844ec9ab (diff) |
fix(node): require.resolve - fallback to global cache when bare specifier from paths not found (#23618)
Part of #22607 (probably closes it, but I haven't done thorough testing)
Makes it so that `require.resolve` with `paths` specified will fallback
to using the global cache when the paths can't be found when using a
global cache (not when using a node_modules folder)
6 files changed, 54 insertions, 8 deletions
diff --git a/ext/node/polyfills/01_require.js b/ext/node/polyfills/01_require.js index 27c10bf58..efde1eb79 100644 --- a/ext/node/polyfills/01_require.js +++ b/ext/node/polyfills/01_require.js @@ -265,9 +265,6 @@ function setupBuiltinModules() { } setupBuiltinModules(); -// Map used to store CJS parsing data. -const cjsParseCache = new SafeWeakMap(); - function pathDirname(filepath) { if (filepath == null) { throw new Error("Empty filepath."); @@ -286,11 +283,10 @@ const nativeModulePolyfill = new SafeMap(); const relativeResolveCache = ObjectCreate(null); let requireDepth = 0; let statCache = null; -let isPreloading = false; let mainModule = null; let hasBrokenOnInspectBrk = false; let hasInspectBrk = false; -// Are we running with --node-modules-dir flag? +// Are we running with --node-modules-dir flag or byonm? let usesLocalNodeModulesDir = false; function stat(filename) { @@ -766,9 +762,7 @@ Module._resolveFilename = function ( if (typeof options === "object" && options !== null) { if (ArrayIsArray(options.paths)) { - const isRelative = op_require_is_request_relative( - request, - ); + const isRelative = op_require_is_request_relative(request); if (isRelative) { paths = options.paths; @@ -848,6 +842,29 @@ Module._resolveFilename = function ( const err = new Error(message); err.code = "MODULE_NOT_FOUND"; err.requireStack = requireStack; + + // fallback and attempt to resolve bare specifiers using + // the global cache when not using --node-modules-dir + if ( + !usesLocalNodeModulesDir && + ArrayIsArray(options?.paths) && + request[0] !== "." && + request[0] !== "#" && + !request.startsWith("file:///") && + !op_require_is_request_relative(request) && + !op_require_path_is_absolute(request) + ) { + try { + return Module._resolveFilename(request, parent, isMain, { + ...options, + paths: undefined, + }); + } catch { + // ignore + } + } + + // throw the original error throw err; }; diff --git a/tests/specs/npm/require_resolve_bad_paths_global_cache/__test__.jsonc b/tests/specs/npm/require_resolve_bad_paths_global_cache/__test__.jsonc new file mode 100644 index 000000000..70840dee2 --- /dev/null +++ b/tests/specs/npm/require_resolve_bad_paths_global_cache/__test__.jsonc @@ -0,0 +1,4 @@ +{ + "args": "run --allow-read main.ts", + "output": "main.out" +} diff --git a/tests/specs/npm/require_resolve_bad_paths_global_cache/main.out b/tests/specs/npm/require_resolve_bad_paths_global_cache/main.out new file mode 100644 index 000000000..563d84ac4 --- /dev/null +++ b/tests/specs/npm/require_resolve_bad_paths_global_cache/main.out @@ -0,0 +1,9 @@ +[UNORDERED_START] +Download http://localhost:4545/npm/registry/@denotest/esm-basic +Download http://localhost:4545/npm/registry/@denotest/require-resolve +[UNORDERED_END] +[UNORDERED_START] +Download http://localhost:4545/npm/registry/@denotest/esm-basic/1.0.0.tgz +Download http://localhost:4545/npm/registry/@denotest/require-resolve/1.0.0.tgz +[UNORDERED_END] +[WILDLINE]@denotest[WILDCHAR]esm-basic[WILDCHAR]1.0.0[WILDCHAR]main.mjs diff --git a/tests/specs/npm/require_resolve_bad_paths_global_cache/main.ts b/tests/specs/npm/require_resolve_bad_paths_global_cache/main.ts new file mode 100644 index 000000000..c3b236c8f --- /dev/null +++ b/tests/specs/npm/require_resolve_bad_paths_global_cache/main.ts @@ -0,0 +1,8 @@ +import "npm:@denotest/esm-basic"; +import { resolve } from "npm:@denotest/require-resolve"; + +console.log(resolve("@denotest/esm-basic", { + // when using the global cache, it should fallback to resolving bare + // specifiers with the global cache when it can't find it via the paths + paths: ["/home"], +})); diff --git a/tests/testdata/npm/registry/@denotest/require-resolve/1.0.0/index.cjs b/tests/testdata/npm/registry/@denotest/require-resolve/1.0.0/index.cjs new file mode 100644 index 000000000..b76925077 --- /dev/null +++ b/tests/testdata/npm/registry/@denotest/require-resolve/1.0.0/index.cjs @@ -0,0 +1,3 @@ +exports.resolve = (...args) => { + return require.resolve(...args); +}; diff --git a/tests/testdata/npm/registry/@denotest/require-resolve/1.0.0/package.json b/tests/testdata/npm/registry/@denotest/require-resolve/1.0.0/package.json new file mode 100644 index 000000000..03631e993 --- /dev/null +++ b/tests/testdata/npm/registry/@denotest/require-resolve/1.0.0/package.json @@ -0,0 +1,5 @@ +{ + "name": "@denotest/require-resolve", + "version": "1.0.0", + "main": "index.cjs" + } |