nodejs / node

Node.js JavaScript runtime ✨🐢🚀✨
https://nodejs.org
Other
106.21k stars 28.91k forks source link

`require.resolve()` and `import.meta.resolve()` doesn't work with self-referenced packages #47681

Open piranna opened 1 year ago

piranna commented 1 year ago

Version

v20.0.0

Platform

Linux executive 5.19.0-40-generic #41-Ubuntu SMP PREEMPT_DYNAMIC Thu Mar 23 21:39:15 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Subsystem

require, import

What steps will reproduce the bug?

Call to require.resolve() created with createRequire(), or to import.meta.resolve(), passing the package name to resolve to itself.

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

Always.

What is the expected behavior? Why is that the expected behavior?

It should return the path of the package itself.

What do you see instead?

node:internal/errors:490
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@mafalda-sfu/mediasoup-cluster-cli' imported from /home/piranna/github/Mafalda/Mediasoup-cluster-CLI/node_modules/@mafalda-sfu/bytenodeify/lib/getBundlesFilenames.js
    at new NodeError (node:internal/errors:399:5)
    at packageResolve (node:internal/modules/esm/resolve:794:9)
    at moduleResolve (node:internal/modules/esm/resolve:843:20)
    at defaultResolve (node:internal/modules/esm/resolve:1070:11)
    at DefaultModuleLoader.resolve (node:internal/modules/esm/loader:306:12)
    at Object.resolve (node:internal/modules/esm/initialize_import_meta:17:25)
    at getBundlesFilenames_priv (file:///home/piranna/github/Mafalda/Mediasoup-cluster-CLI/node_modules/@mafalda-sfu/bytenodeify/lib/getBundlesFilenames.js:31:32)
    at file:///home/piranna/github/Mafalda/Mediasoup-cluster-CLI/node_modules/@mafalda-sfu/bytenodeify/lib/getBundlesFilenames.js:86:17
    at Array.map (<anonymous>)
    at default (file:///home/piranna/github/Mafalda/Mediasoup-cluster-CLI/node_modules/@mafalda-sfu/bytenodeify/lib/getBundlesFilenames.js:81:38) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Additional information

Not sure if it happens with CommonJS require() too, or just only with ESM related resolve functions.

piranna commented 1 year ago

When using require.resolve.paths() from createRequire(), all paths end with node_modules, none of them points to the current project root folder.

benjamingr commented 1 year ago

@nodejs/loaders

targos commented 1 year ago

Can you please provide a simple reproducible example? In the stack trace you posted, it doesn't look like you are trying to self-reference a package. The error says @mafalda-sfu/mediasoup-cluster-cli cannot be found from a file located under @mafalda-sfu/bytenodeify

piranna commented 1 year ago

In the stack trace you posted, it doesn't look like you are trying to self-reference a package. The error says @mafalda-sfu/mediasoup-cluster-cli cannot be found from a file located under @mafalda-sfu/bytenodeify

@mafalda-sfu/bytenodeify is one of the devDependencies of @mafalda-sfu/mediasoup-cluster-cli, its actual location is /home/piranna/github/Mafalda/Mediasoup-cluster-CLI.

ef4 commented 1 year ago

I can reproduce this with anything that appears in package.json exports.

Given package.json:

{
   "name": "my-package",
   "exports": {
      ".": "./main.js"
   }
}

Make sure main.js exists.

In interactive node, run require.resolve('my-package') from inside the package, and it will correctly return the path to main.js

But then from a different directory not within my-package, again enter node interactive cli and this time try:

require.resolve('my-package', { paths: [ pathToMyPackage ] })

It will throw MODULE_NOT_FOUND.

This seems to show that the self-reference lookup is always using process.cwd() instead of respecting the paths argument.

Edit to add: I reproduced this on both Node v20.5.0 and v16.20.0.

GeoffreyBooth commented 1 year ago

from a different directory not within my-package

The feature is defined as working from within the package. See https://nodejs.org/api/packages.html#self-referencing-a-package-using-its-name:

Within a package, the values defined in the package’s package.json ["exports"](https://nodejs.org/api/packages.html#exports) field can be referenced via the package’s name.

ef4 commented 1 year ago

So if I set paths to a directory within the package it should resolve all the things that work within the package, yes?

piranna commented 1 year ago

So if I set paths to a directory within the package it should resolve all the things that work within the package, yes?

Yes, that's just the definition of self-reference import :-)