Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression: require.resolve(".", { paths }) behaves differently from require.resolve("./", { paths }) #47000

Closed
tolmasky opened this issue Mar 7, 2023 · 1 comment · Fixed by #56735

Comments

@tolmasky
Copy link
Contributor

tolmasky commented Mar 7, 2023

Version

18.14.2

Platform

22.3.0 Darwin Kernel Version 22.3.0

Subsystem

loader

What steps will reproduce the bug?

home:/$ docker run --rm -it node:18.14.2-slim bash
node:/# echo "['./', '.'].map(request => console.log(require.resolve(request, { paths: ['..'] })))" > index.js
node:/# mkdir test && cd test
node:/# node ../index.js

This produces:

> /index.js
> node:internal/modules/cjs/loader:1078
  throw err;
  ^

Error: Cannot find module '.'
Require stack:
- /index.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1075:15)
    at Function.resolve (node:internal/modules/cjs/helpers:116:19)
    at /index.js:1:48
    at Array.map (<anonymous>)
    at Object.<anonymous> (/index.js:1:13)
    at Module._compile (node:internal/modules/cjs/loader:1254:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)
    at Module.load (node:internal/modules/cjs/loader:1117:32)
    at Module._load (node:internal/modules/cjs/loader:958:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ '/index.js' ]
}
node:/#

The same is true of .. and ../. I leave that as an exercise to the reader. If you rerun the above in node 10, you get the same log for both, as expected:

home:/$ docker run --rm -it node:10.24.1-slim bash
node:/# echo "['./', '.'].map(request => console.log(require.resolve(request, { paths: ['..'] })))" > index.js
node:/# mkdir test && cd test
node:/# node ../index.js
/index.js
/index.js
node:/#

If you want to get more clever, you can put a index.js inside of the test directory, and then it'll just give you different results without crashing:

home:/$ docker run --rm -it node:18.14.2-slim bash
node:/# echo "['./', '.'].map(request => console.log(require.resolve(request, { paths: ['..'] })))" > index.js
node:/# mkdir test && cd test
node:/# echo "['./', '.'].map(request => console.log(require.resolve(request, { paths: ['..'] })))" > index.js
node:/# node ../index.js
/index.js
/test/index.js
node:/#

How often does it reproduce? Is there a required condition?

Every time.

What is the expected behavior?

The same way it worked in node 10:

home:/$ docker run --rm -it node:10.24.1-slim bash
node:/# echo "['./', '.'].map(request => console.log(require.resolve(request, { paths: ['..'] })))" > index.js
node:/# mkdir test && cd test
node:/# node ../index.js
/index.js
/index.js
node:/#

What do you see instead?

Different file paths, crash, etc.

Additional information

This seems to be a result of this pull request: #27598

The code in Module._resolveFilename only checks for "./" and "../" to determine if the path is a relative path:

const isRelative = StringPrototypeStartsWith(request, './') ||
StringPrototypeStartsWith(request, '../') ||
((isWindows && StringPrototypeStartsWith(request, '.\\')) ||
StringPrototypeStartsWith(request, '..\\'));

Adding === "." and === ".." should fix the problem. Or, given that earlier in the file in Module._findPath the same thing is calculated slightly differently:

const isRelative = StringPrototypeCharCodeAt(request, 0) === CHAR_DOT &&
(
request.length === 1 ||
StringPrototypeCharCodeAt(request, 1) === CHAR_FORWARD_SLASH ||
(isWindows && StringPrototypeCharCodeAt(request, 1) === CHAR_BACKWARD_SLASH) ||
(StringPrototypeCharCodeAt(request, 1) === CHAR_DOT && ((
request.length === 2 ||
StringPrototypeCharCodeAt(request, 2) === CHAR_FORWARD_SLASH) ||
(isWindows && StringPrototypeCharCodeAt(request, 2) === CHAR_BACKWARD_SLASH)))

Perhaps this should be factored out into a isRelativePath function since it seems to be tricky enough to get right to not rely on separate inlined implementations in various different places.

@bjrmatos
Copy link

i just got hit by this today, and when debugging i found the solution the same as the linked PR #47019

is anything missing to fix this? or what needs to be done to move forward with the PR?

dario-piotrowicz added a commit to dario-piotrowicz/node that referenced this issue Jan 23, 2025
dario-piotrowicz added a commit to dario-piotrowicz/node that referenced this issue Jan 23, 2025
dario-piotrowicz added a commit to dario-piotrowicz/node that referenced this issue Jan 23, 2025
dario-piotrowicz added a commit to dario-piotrowicz/node that referenced this issue Jan 24, 2025
…tive

Fixes: nodejs#47000

add early return for perf gain

fix linting
dario-piotrowicz added a commit to dario-piotrowicz/node that referenced this issue Jan 24, 2025
this change fixes `require.resolve` used with the `paths` option
not considering `.` and `..` as relative

Fixes: nodejs#47000
dario-piotrowicz added a commit to dario-piotrowicz/node that referenced this issue Jan 24, 2025
this change fixes `require.resolve` used with the `paths` option
not considering `.` and `..` as relative

Fixes: nodejs#47000
aduh95 pushed a commit that referenced this issue Jan 27, 2025
this change fixes `require.resolve` used with the `paths` option
not considering `.` and `..` as relative

Fixes: #47000
PR-URL: #56735
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jordan Harband <ljharb@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
aduh95 pushed a commit that referenced this issue Jan 30, 2025
this change fixes `require.resolve` used with the `paths` option
not considering `.` and `..` as relative

Fixes: #47000
PR-URL: #56735
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jordan Harband <ljharb@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
hvanness pushed a commit to hvanness/node that referenced this issue Jan 30, 2025
this change fixes `require.resolve` used with the `paths` option
not considering `.` and `..` as relative

Fixes: nodejs#47000
PR-URL: nodejs#56735
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jordan Harband <ljharb@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
aduh95 pushed a commit that referenced this issue Jan 31, 2025
this change fixes `require.resolve` used with the `paths` option
not considering `.` and `..` as relative

Fixes: #47000
PR-URL: #56735
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jordan Harband <ljharb@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
aduh95 pushed a commit that referenced this issue Feb 4, 2025
this change fixes `require.resolve` used with the `paths` option
not considering `.` and `..` as relative

Fixes: #47000
PR-URL: #56735
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jordan Harband <ljharb@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
aduh95 pushed a commit that referenced this issue Feb 6, 2025
this change fixes `require.resolve` used with the `paths` option
not considering `.` and `..` as relative

Fixes: #47000
PR-URL: #56735
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jordan Harband <ljharb@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants