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

Failed to resolve 'dunder-proto/get' from './node_modules/get-intrinsic/index.js' #2

Closed
KetanShindeAsurion opened this issue Dec 11, 2024 · 29 comments

Comments

@KetanShindeAsurion
Copy link

Facing this error -> Failed to resolve 'dunder-proto/get' from './node_modules/get-intrinsic/index.js'

here is the line it fails at -> var getDunderProto = require('dunder-proto/get');
Which is part of third party get-intrinsic module.

[build-proxy] npm run build-proxy exited with code 0
[build-ui] Building...
[build-ui] 🚨 Build failed.
[build-ui] 
[build-ui] @parcel/core: Failed to resolve 'dunder-proto/get' from './node_modules/get-intrinsic/index.js'
[build-ui] 
[build-ui]   /**********/node_modules/get-intrinsic/index.js:46:30
[build-ui]     45 | var hasSymbols = require('has-symbols')();
[build-ui]   > 46 | var getDunderProto = require('dunder-proto/get');
[build-ui]   >    |                              ^^^^^^^^^^^^^^^^^^
[build-ui]     47 | 
[build-ui]     48 | var getProto = (typeof Reflect === 'function' && Reflect.getPrototypeOf)
[build-ui] 
[build-ui] 
[build-ui] 
[build-ui] @parcel/resolver-default: Error parsing JSON
[build-ui]   /**********/node_modules/dunder-proto/package.json:5:14
[build-ui]     4 |   "description": "If available, the `Object.prototype.__proto__` accessor and mutator, call-bound",
[build-ui]   > 5 |   "main": false,
[build-ui]   >   |               ^ invalid type: boolean `false`, expected path string at line 5 column 14
[build-ui]     6 |   "exports": {
[build-ui]     7 |     "./get": "./get.js",

Any idea how can I fix this?

@ljharb
Copy link
Member

ljharb commented Dec 11, 2024

It seems like a parcel bug (@parcel/resolver-default specifically) - false is a valid value for main in package.json. I'd suggest filing it there.

@ClemensLey
Copy link

We are having the same issue. Setting main in package.json to a boolean is not mentioned in the docs for package.json. As far as I can tell the error on Parcel is justified. It would really help us out if this could be fixed, thanks!

@ljharb
Copy link
Member

ljharb commented Dec 12, 2024

npm's docs aren't relevant, since it's always been accepted by node. The error on Parcel is flatly incorrect.

There's been lots of working resolution implementations for over a decade - primarily https://npmjs.com/resolve - so if a tool decides to rewrite it from scratch, it's incumbent on them to look at existing implementations and not just the docs.

@ClemensLey
Copy link

ClemensLey commented Dec 12, 2024

What is the meaning/purpose of setting main to false?

@ljharb
Copy link
Member

ljharb commented Dec 12, 2024

So that require('math-instrinics') fails. It's identical to setting it to a string that points to a nonexistent file, but with clearer semantics.

@ClemensLey
Copy link

I see, that makes sense.

I asked an AI about different ways to do this and one suggestion was to point to an existing file that throws an error. One advantage would be that you can control the error message. If you could find a solution that has both a clear semantics and works well with bundlers that would be very helpful to us and I think the community at large.

Also, thank you for your open source work!

@ljharb
Copy link
Member

ljharb commented Dec 12, 2024

I could definitely make that change - but the only bundler that seems to be broken here is parcel, and I'd hate to worsen the ecosystem by working around it rather than trying to push parcel to fix itself. Have you filed an issue with them?

@ClemensLey
Copy link

Ok, I will create an issue on parcel. Do you know of a good source that I can refer to where the correct semantics of the main filed is described?

@ljharb
Copy link
Member

ljharb commented Dec 12, 2024

I mean, in this case nothing's actually trying to import the main anyways, so parcel shouldn't be looking at it at all - but "do whatever node does" is pretty straightforward.

@ClemensLey
Copy link

Is that documented in the node docs? I'm all for getting them to do the right thing but it would help to be able to refer to something

@ljharb
Copy link
Member

ljharb commented Dec 12, 2024

https://nodejs.org/api/modules.html#all-together is the algorithm. Specifically:

LOAD_AS_DIRECTORY(X)

  1. If X/package.json is a file,
    a. Parse X/package.json, and look for "main" field.
    b. If "main" is a falsy value, GOTO 2.

meaning it supports any falsy value, and the next steps stringify any truthy value.

@ClemensLey
Copy link

A different location of the node docs says: "The "main" field defines the entry point of a package when imported by name via a node_modules lookup. Its value is a path." So there is an incompatibility in the node docs. You are relying on one statement and the Parcel team is relying on another

@ljharb
Copy link
Member

ljharb commented Dec 12, 2024

Right. Which is why the docs never matter more than the actual implementation, for which "main": false has worked fine for a decade and a half.

@ClemensLey
Copy link

Imo, if the goal it to provide code with a clear semantics it's best not to use constructs over which there is some confusion. If unavoidable maybe but in this case I think there are easy fixes. My VS code also gives a warning for that line by the way.

Image

@ljharb
Copy link
Member

ljharb commented Dec 12, 2024

yes, the jsonschema that vscode uses for package.json is also incorrect, sadly.

@devongovett
Copy link

Oh come on. Why is this necessary? You could just remove the main field entirely from your package. That would have the exact same effect without breaking compatibility. There's no reason to set it to false at all. I will change this in Parcel but this is silly and a waste of everyone's time.

@ljharb
Copy link
Member

ljharb commented Dec 16, 2024

@devongovett it's a standard thing that's in numerous packages throughout the ecosystem. It seems like Parcel not doing what npm has always done is the thing that's wasted the most time here?

Removing the main field is not the same - that defaults to index.js, which if it exists would allow it to be imported. Setting it to false is objectively clearer and more correct than omitting it, and ensures that nobody can unintentionally add an entrypoint to the package.

@devongovett
Copy link

it's a standard thing that's in numerous packages throughout the ecosystem

It is now that you've done it. We've never had this issue come up before.

Removing the main field is not the same - that defaults to index.js

That's not true. Following the algorithm you posted above:

If "main" is a falsy value, GOTO 2.
...
2. LOAD_INDEX(X)

@ljharb
Copy link
Member

ljharb commented Dec 16, 2024

@devongovett i'm not the first one to do it; as i said, this is how node itself, and the ecosystem, has always worked. That it's never come up before just means the overlap of "someone using parcel" and "someone using a package that does this somewhere in their graph" hasn't occurred before.

yes - "GOTO 2" then does "LOAD_INDEX". meaning it defaults to index.js.

This is all empirically observable in every version of node that's ever existed, as well as resolve, and every other resolution tool and bundler in the ecosystem. I'm not sure why you're giving this much pushback when Parcel is the only tool in existence that seems to have this problem.

@devongovett
Copy link

meaning it defaults to index.js

right, exactly what removing the main field would do.

I'm not sure why you're giving this much pushback when Parcel is the only tool in existence that seems to have this problem.

As I said, I'm gonna fix it but this is silly.

@ljharb
Copy link
Member

ljharb commented Dec 16, 2024

As long as it gets fixed, that's fine. Your belief in what's silly is unfortunately irrelevant, because the ecosystem works the way it works ¯\_(ツ)_/¯

I'd strongly suggest auditing your resolution algorithm and comparing it to node itself, just to make sure there's no additional issues and that this isn't a brown m&m.

@ljharb
Copy link
Member

ljharb commented Dec 16, 2024

Seems like this is somewhat fixed in parcel-bundler/parcel#10053, so I'll close this.

@ljharb ljharb closed this as completed Dec 16, 2024
@EddieGr
Copy link

EddieGr commented Dec 17, 2024

Thank you. Updated to parcel@2.13.3 and and it works.

@alshdavid
Copy link

It appears that boolean is not a valid value for package.json#main according to the Nodejs docs however the Nodejs resolution specification defines that main is ignored if exports are present.

In the case of this package, if preserving support for older versions of Nodejs is important, the main field should be updated to be a valid relative path (string) otherwise the key should be removed entirely.

Nodejs follows this resolution circuit lazily for package.json#type: commonjs | undefined

  • package.json#exports
    • [...customConditions, node-addons, node, import, require, module-sync, default]
  • package.json#main
    • main must be a string and it will throw if it's another type (boolean, number, Object, etc)
    • If main throws then check for ./index.js in the package root
  • Otherwise throw a resolution error

So boolean is an invalid property for main - but it works because Nodejs evaluates exports first and doesn't validate main.

@ljharb
Copy link
Member

ljharb commented Jan 14, 2025

@alshdavid even in node versions that predate exports, false works fine, and ensures that require.resolve('dunder-proto') throws. exports has nothing to do with it, since node refused to ever alter the non-exports resolution algorithm, and hasn't.

@alshdavid
Copy link

alshdavid commented Jan 14, 2025

Works how? as in it falls back to ./index.js?

Looking at node 12, the behaviour is the same as node 22:

Image

  • Resolve main
    • if main is a string then resolve path
      • if path does not exist then exit with error
    • If main is not a string fallback to ./index.js
      • if index.js does not exist then exit with error
  • exit with error

The type that main specifies doesn't matter though it is technically incorrect to specify false as the value

@ljharb
Copy link
Member

ljharb commented Jan 14, 2025

Yes, that's what I'm saying, it works in that it falls back to the (nonexistent) index.js.

What is technically correct is that the type doesn't matter - so, despite a number of places documenting it as a string, in fact it can be literally any kind of JSON value, and since there's semantic value and quite a bit of precedent for packages using false, specifically, it's something docs and JSON schemas and whatnot should be documenting.

@alshdavid
Copy link

alshdavid commented Jan 14, 2025

Yeah I see your point. Bundler resolvers should probably take this into account.

Essentially, setting main: false is the same as setting main: index.js by relying on an exception to be thrown in the Nodejs resolver to get there.

That said, this package doesn't have an index.js - so regardless of the main: false or main: index.js- it should be removed for that reason alone 😆

@ljharb
Copy link
Member

ljharb commented Jan 14, 2025

Correct, it doesn't, because I don't want this package to unintentionally have a main. I could remove it, or set it to index.js while the file doesn't exist, and then it would be implicitly documented - but instead, I chose the superior option, to explicitly document it as false (while the file doesn't exist)

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

6 participants