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

NodeJS - How the LOAD_SELF_REFERENCE of the “require” function works? #2699

Closed
hopeless-programmer-online opened this issue May 14, 2020 · 3 comments

Comments

@hopeless-programmer-online
Copy link

hopeless-programmer-online commented May 14, 2020

  • Node.js Version:
    v13.12.0
  • OS:
    Windows 7
  • Scope (install, code, runtime, meta, other?):
    Runtime/docs.
  • Module (and version) (if relevant):
    Require.

Since nobody answer my question on stack overflow I duplicate it here.

According to NodeJS docs, the require function has a loading stage named LOAD_SELF_REFERENCE. It has the following pseudo-code:

LOAD_SELF_REFERENCE(X, START)
1. Find the closest package scope to START.
2. If no scope was found, return.
3. If the `package.json` has no "exports", return.
4. If the name in `package.json` isn't a prefix of X, throw "not found".
5. Otherwise, load the remainder of X relative to this package as if it was loaded via `LOAD_NODE_MODULES` with a name in `package.json`.

I assume that this algorithm resolves modules, which are nested inside the same package as the "require" caller. For instance, calling require("a/x") from a/y.js.

According to (4.), if the name in package.json is not a prefix of X the algorithm should throw an error. So I assume that the following code and the folders structure should crash:

node_modules
|-a
  |-package.json
  |-a.js
|-b
  |-package.json
  |-b.js
  |-x.js

where:

node_modules/a/package.json:

{
    "name": "a",
    "main": "./a",
    "exports": {
        ".": "./a"
    }
}

node_modules/a/a.js:

require("b/x");

node_modules/b/package.json:

{
    "name": "b",
    "main": "./b",
    "exports": {
        ".": "./b",
        "./x": "x"
    }
}

But it somehow works.
Is this a mistake in documentation? Or I interpret the pseudo-code incorrectly?

Please, advice. Thanks.

@addaleax
Copy link
Member

@hopeless-programmer-online I’m not sure what the contents of the files are that are only referenced here but not listed in your issue, i.e. b/b.js and b/x.js. I’m not sure those are relevant, either, but are you sure that you gave the Node.js version that you’re using correctly? Node 12 doesn’t support "exports": by default, so if you’re using Node 12 rather than Node 13 it would work.

With your example and Node 13, I am getting an exception thrown, as you are expecting.

@guybedford
Copy link

guybedford commented May 14, 2020

@hopeless-programmer-online you are correct - this is a bug in the written specification! I've posted a fix in nodejs/node#33391.

@hopeless-programmer-online
Copy link
Author

@guybedford thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants