GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — module: fix extension searching for exports by guybedford · Pull Request #32351 · nodejs/node

Conversation

@guybedford

@guybedford guybedford commented Mar 18, 2020

Copy link
Copy Markdown
Contributor

This PR disables extension searching for the CommonJS exports implementation.

The catch with supporting extension searching for exports on CommonJS is having differences between the ESM and CJS implementations so this brings the gap back together on this, as it really should have been to begin with I think.

Please review @addaleax @jkrems when you can. Would be good to get this out soon as it is a breaking change under the experimental status.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

bricss, himself65, and ExE-Boss reacted with thumbs up emoji
All reactions
  • 👍 3 reactions
@guybedford
guybedford requested review from addaleax and hybrist March 18, 2020 23:53
@guybedford

guybedford commented Mar 19, 2020

Copy link
Copy Markdown
Contributor Author

//cc @nodejs/modules-active-members I would like to try and get this landed for the release next week if possible (and possibly before the next meeting). Please take a look if you have time.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

GeoffreyBooth
GeoffreyBooth approved these changes Mar 19, 2020
View reviewed changes
bmeck
bmeck approved these changes Mar 20, 2020
View reviewed changes
Comment thread doc/api/modules.md Resolved

Uh oh!

There was an error while loading. Please reload this page.

hybrist
hybrist approved these changes Mar 20, 2020
View reviewed changes
@ljharb

ljharb commented Mar 20, 2020

Copy link
Copy Markdown
Member

I very much disagree with this; CommonJS means extension searching, and every context that involves CJS should always support it.

This, thus, does not have modules group consensus, and I'd prefer we discuss it before landing it.

weswigham reacted with thumbs up emoji ExE-Boss reacted with thumbs down emoji
All reactions
  • 👍 1 reaction
  • 👎 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ljharb

ljharb commented Mar 20, 2020

Copy link
Copy Markdown
Member

If we want CJS and ESM to be the same, the path to that is adding extension searching to ESM, not the reverse.

ExE-Boss reacted with thumbs down emoji
All reactions
  • 👎 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@GeoffreyBooth

GeoffreyBooth commented Mar 20, 2020 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

"exports" is its own definition. It breaks with "main" in that it requires specifiers begin with ./, for example. Also requiring explicit extensions just makes logical sense, as extensions are required for ESM and "exports" applies to both CommonJS and ESM, so therefore it needs to require the more restrictive rule for both systems.

ExE-Boss reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@nodejs-github-bot

nodejs-github-bot commented Mar 23, 2020

Copy link
Copy Markdown
Collaborator

CI: https://ci.nodejs.org/job/node-test-pull-request/29983/

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@guybedford

guybedford commented Mar 23, 2020

Copy link
Copy Markdown
Contributor Author

For an example of the problem this is fixing see Babel at babel/babel#11283, where require('babel-compat-data/corejs-shipped-proposals') would work fine but import('babel-compat-data/corejs-shipped-proposals') wouldn't. This is very clearly a footgun that is important to patch.

@ljharb I would really like to get this out in the coming 13 release before the meeting if you would reconsider your objection.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ljharb

ljharb commented Mar 23, 2020

Copy link
Copy Markdown
Member

I feel very strongly that anything CJS should always have extension and index searching.

ExE-Boss reacted with thumbs down emoji
All reactions
  • 👎 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@guybedford

guybedford commented Mar 23, 2020 via email

Copy link
Copy Markdown
Contributor Author
There is very clearly a mutually exclusive choice here between having full parity of exports resolution between esm and cjs and supporting extension searching. If it comes down to it, there is simply no way we would change the esm implementation to support extension searching. So we arrive at this local non optimal footgun position. That will be the only outcome, and if that must be it then ok, but it would be a shame for users.
…
On Mon, Mar 23, 2020 at 08:16 Jordan Harband ***@***.***> wrote: I feel very strongly that anything CJS should always have extension and index searching. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub <#32351 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AAESFSSEDXU4PKEEQAOPLP3RI35DBANCNFSM4LO46XHA> .
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mhdawson mhdawson mentioned this pull request Mar 23, 2020
Node.js Modules Team Meeting 2020-03-25 nodejs/modules#497
Closed
@guybedford guybedford added the modules-agenda Issues and PRs to discuss during Modules team meetings. label Mar 23, 2020
@bmeck

bmeck commented Mar 23, 2020

Copy link
Copy Markdown
Member

I'd agree with @guybedford , having the field vary between CJS and ESM usage would lead to fragmentation. We need to pick a single choice to always, or never do extension searching for the field. I'd prefer we pick the simpler, non-searching behavior as it is easier for tools to coordinate around that form rather than when we might not know which extensions are supported in CJS at the current time of evaluation (people mutating require.extensions).

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

MylesBorins
MylesBorins approved these changes Mar 25, 2020
View reviewed changes

@MylesBorins MylesBorins left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@MylesBorins

MylesBorins commented Mar 25, 2020

Copy link
Copy Markdown
Contributor

FWIW my LGTM is dependent on discussion in the modules team and ensuring there are no large concerns with it. So please do not land yet

ljharb reacted with heart emoji
All reactions
  • ❤️ 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@MylesBorins MylesBorins added the blocked PRs that are blocked by other issues or PRs. label Mar 25, 2020
@GeoffreyBooth

GeoffreyBooth commented Mar 25, 2020

Copy link
Copy Markdown
Member

There's another complication. Here's how CommonJS treats trailing slashes today:

// ./main.js
require('./folder/');

// ./folder/index.js
console.log('hi');
node ./main.js
hi

Yet, of course, per the "exports" spec a trailing slash means “map everything in this folder.”

So the existing behavior doesn't actually match CommonJS searching behavior already.

ljharb reacted with eyes emoji
All reactions
  • 👀 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@hybrist

hybrist commented Mar 25, 2020

Copy link
Copy Markdown
Contributor

So the existing behavior doesn't actually match CommonJS searching behavior already.

Trying to parse how your example relates to exports. Maybe something like the following:

require('pkg/mapped/path/custom/part/');

Where pkg would have an entry for ./mapped/path/ I assume? And the argument is that it would fail (?) for the trailing slash when using exports (does it?)?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ljharb

ljharb commented Mar 25, 2020

Copy link
Copy Markdown
Member

In CJS, you'd use foo/bar/path/ to differentiate between foo/bar/path.js and foo/bar/path/index.js (or wherever foo/bar/path/package.json pointed) - so @GeoffreyBooth is right that this is an unavoidable and preexisting deviation between CJS and exports maps.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@GeoffreyBooth

GeoffreyBooth commented Mar 25, 2020 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Test A, traditional CommonJS:

// ./main.js
require('foo/'); // Note the trailing slash

// ./node_modules/foo/dist/index.js
console.log('hi');

// ./node_modules/foo/package.json
{ "main": "./dist/index.js" }
node ./main.js
hi

Test B, with "exports":

// ./main.js and ./node_modules/foo/dist/index.js unchanged from A

// ./node_modules/foo/package.json
{ "exports": "./dist/index.js" }
node ./main.js
internal/modules/cjs/loader.js:524
  throw new ERR_PACKAGE_PATH_NOT_EXPORTED(basePath, mappingKey);
  ^

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './' is not defined by "exports" in /private/tmp/test/node_modules/foo/package.json
    at applyExports (internal/modules/cjs/loader.js:524:9)
    at resolveExports (internal/modules/cjs/loader.js:541:12)
    at Function.Module._findPath (internal/modules/cjs/loader.js:661:22)
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:963:27)
    at Function.Module._load (internal/modules/cjs/loader.js:859:27)
    at Module.require (internal/modules/cjs/loader.js:1036:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at Object.<anonymous> (/private/tmp/test/main.js:1:1)
    at Module._compile (internal/modules/cjs/loader.js:1147:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1167:10) {
  code: 'ERR_PACKAGE_PATH_NOT_EXPORTED'
}
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@hybrist

hybrist commented Mar 25, 2020

Copy link
Copy Markdown
Contributor

Right, but that example is just any unexported path which isn't specific to trailing slash afaict?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@GeoffreyBooth

GeoffreyBooth commented Mar 25, 2020

Copy link
Copy Markdown
Member

Right, but that example is just any unexported path which isn't specific to trailing slash afaict?

Well it just doesn't match the CommonJS behavior. If in test B you change require('foo/') to require('foo') it works; whereas in CommonJS, either would work.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@hybrist

hybrist commented Mar 25, 2020

Copy link
Copy Markdown
Contributor

If in test B you change require('foo/') to require('foo') it works; whereas in CommonJS, either would work.

Adding a trailing slash changes the behavior, that's not really the same thing. require('foo/bar') and require('foo/bar/') won't behave the same. And if node_modules/foo.js exists, then require('foo') and require('foo/') won't do the same thing either. This feels unrelated to exports..?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ljharb

ljharb commented Mar 25, 2020

Copy link
Copy Markdown
Member

What I think they're saying is that foo/ without exports, doesn't map to what foo/ means in exports.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@guybedford
module: fix no extension searching for exports
f399cfd
@guybedford
guybedford force-pushed the exports-no-ext branch from 92fc811 to 17e65cf Compare March 25, 2020 23:49
@guybedford

guybedford commented Mar 25, 2020

Copy link
Copy Markdown
Contributor Author

As discussed in the meeting, I've added the new commit to retain extension searching for folder exports in CommonJS exports resolution only, along with tests of the various lookups.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@MylesBorins MylesBorins removed the modules-agenda Issues and PRs to discuss during Modules team meetings. label Mar 26, 2020
@nodejs-github-bot

This comment has been minimized.

Sign in to view
ljharb
ljharb reviewed Mar 26, 2020
View reviewed changes
Comment thread lib/internal/modules/cjs/loader.js Outdated

@ljharb ljharb Mar 26, 2020

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will delete require('path').resolve break this code?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@guybedford guybedford Mar 26, 2020

Copy link
Copy Markdown
Contributor Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, although there are a lot of calls to path.resolve within this module, so changing that is best done as a separate refactoring.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

ljharb and ExE-Boss reacted with thumbs up emoji
All reactions
  • 👍 2 reactions
Comment thread lib/internal/modules/cjs/loader.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

@guybedford
guybedford force-pushed the exports-no-ext branch from 84baa57 to bfe4cab Compare March 26, 2020 14:48
@guybedford
module: CJS extension searching for folder exports
ce967de
@guybedford
guybedford force-pushed the exports-no-ext branch from bfe4cab to ce967de Compare March 26, 2020 14:51
GeoffreyBooth
GeoffreyBooth approved these changes Mar 26, 2020
View reviewed changes
@nodejs-github-bot

nodejs-github-bot commented Mar 26, 2020

Copy link
Copy Markdown
Collaborator

CI: https://ci.nodejs.org/job/node-test-pull-request/30098/

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

ljharb
ljharb reviewed Mar 26, 2020
View reviewed changes
Comment thread lib/internal/modules/cjs/loader.js

const basePath = path.resolve(nmPath, name);
return applyExports(basePath, expansion);
const [, name, expansion = ''] =

@ljharb ljharb Mar 26, 2020

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using array destructuring means it will break if Symbol.iterator is deleted off of Array.prototype. this one has a lot of places in the codebase to fix, tho, so it’s probably fine to skip for now.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@nodejs-github-bot

nodejs-github-bot commented Mar 29, 2020

Copy link
Copy Markdown
Collaborator

CI: https://ci.nodejs.org/job/node-test-pull-request/30173/

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

guybedford added a commit that referenced this pull request Apr 1, 2020
@guybedford
module: path-only CJS exports extension searching
534c204
PR-URL: #32351
Reviewed-By: Geoffrey Booth <[email protected]>
Reviewed-By: Bradley Farias <[email protected]>
Reviewed-By: Jan Krems <[email protected]>
Reviewed-By: Myles Borins <[email protected]>
@guybedford

guybedford commented Apr 1, 2020

Copy link
Copy Markdown
Contributor Author

Landed in 534c204.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@guybedford guybedford closed this Apr 1, 2020
BethGriggs pushed a commit that referenced this pull request Apr 7, 2020
@guybedford @BethGriggs
module: path-only CJS exports extension searching
b2e7700
PR-URL: #32351
Reviewed-By: Geoffrey Booth <[email protected]>
Reviewed-By: Bradley Farias <[email protected]>
Reviewed-By: Jan Krems <[email protected]>
Reviewed-By: Myles Borins <[email protected]>
targos pushed a commit that referenced this pull request Apr 12, 2020
@guybedford @targos
module: path-only CJS exports extension searching
bc7f819
PR-URL: #32351
Reviewed-By: Geoffrey Booth <[email protected]>
Reviewed-By: Bradley Farias <[email protected]>
Reviewed-By: Jan Krems <[email protected]>
Reviewed-By: Myles Borins <[email protected]>
@targos targos mentioned this pull request Apr 13, 2020
v13.13.0 release proposal #32813
Merged
@JLHwung JLHwung mentioned this pull request Apr 14, 2020
Errors from conditional exports after upgraded to Node 13.13 #32852
Closed
MylesBorins pushed a commit to MylesBorins/node that referenced this pull request Apr 16, 2020
@guybedford @MylesBorins
module: path-only CJS exports extension searching
98dec2c
PR-URL: nodejs#32351
Reviewed-By: Geoffrey Booth <[email protected]>
Reviewed-By: Bradley Farias <[email protected]>
Reviewed-By: Jan Krems <[email protected]>
Reviewed-By: Myles Borins <[email protected]>
@MylesBorins MylesBorins mentioned this pull request Apr 16, 2020
[v12.x] module: path-only CJS exports extension searching #32883
Closed
MylesBorins pushed a commit that referenced this pull request Apr 17, 2020
@guybedford @MylesBorins
module: path-only CJS exports extension searching
717f9c5
Backport-PR-URL: #32883
PR-URL: #32351
Reviewed-By: Geoffrey Booth <[email protected]>
Reviewed-By: Bradley Farias <[email protected]>
Reviewed-By: Jan Krems <[email protected]>
Reviewed-By: Myles Borins <[email protected]>
@targos targos mentioned this pull request Apr 22, 2020
v12.16.3 release proposal #33009
Merged
michaelsbradleyjr added a commit to embarklabs/embark that referenced this pull request Apr 24, 2020
@michaelsbradleyjr
build(deps): bump @babel/preset-env to >= 7.9.0
f2ef50c
Node v13.13.0 introduced a change that is incompatible with `@babel/preset-env`
versions `< 7.9.0`.

See:

nodejs/node#32351
nodejs/node#32852
babel/babel#11283

Bump our direct dependencies to `7.9.5` and manually cause additional bumps in
`yarn.lock` that result in all versions of `@babel/preset-env` installed in the
monorepo's `node_modules` trees being `>= 7.9.0`.
@michaelsbradleyjr michaelsbradleyjr mentioned this pull request Apr 24, 2020
build(deps): bump @babel/preset-env to >= 7.9.0 embarklabs/embark#2367
Merged
michaelsbradleyjr added a commit to embarklabs/embark that referenced this pull request Apr 24, 2020
@michaelsbradleyjr
build(deps): bump @babel/preset-env to >= 7.9.0
32dc886
Node v13.13.0 introduced a change that is incompatible with `@babel/preset-env`
versions `< 7.9.0`.

See:
* nodejs/node#32351
* nodejs/node#32852
* babel/babel#11283

Bump our direct dependencies to `7.9.5` and manually cause additional bumps in
`yarn.lock` that result in all versions of `@babel/preset-env` installed in the
monorepo's `node_modules` trees being `>= 7.9.0`.
michaelsbradleyjr added a commit to embarklabs/embark that referenced this pull request Apr 24, 2020
@michaelsbradleyjr
build(deps): bump @babel/preset-env to >= 7.9.0
44dfb99
Node v13.13.0 introduced a change that is incompatible with `@babel/preset-env`
versions `< 7.9.0`.

See:
* nodejs/node#32351
* nodejs/node#32852
* babel/babel#11283

Bump our direct dependencies to `7.9.5` and manually cause additional bumps in
`yarn.lock` that result in all versions of `@babel/preset-env` installed in the
monorepo's `node_modules` trees being `>= 7.9.0`.
ralish added a commit to draftable/compare-api-node-client that referenced this pull request Jun 22, 2020
@ralish
Update Babel packages to fix Node.js import error
caa4760
Due to the following breaking change:
nodejs/node#32351

This fixes compatibility with Node.js:
- v12.17.0+
- v13.13.0+

It probably also makes us compatible with Node.js v14.
@ljharb ljharb mentioned this pull request Sep 24, 2020
add support for the exports package.json attribute browserify/resolve#224
Draft
@marlenecota marlenecota mentioned this pull request Mar 3, 2021
update @babel/preset-env to ^7.9.0 microsoft/react-native-svg-desktop#6
Merged
@Cherry Cherry mentioned this pull request Oct 4, 2026
module: cache "exports" resolutions in _findPath #66514
Open
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@ljharb ljharb ljharb left review comments
@GeoffreyBooth GeoffreyBooth GeoffreyBooth approved these changes
@hybrist hybrist hybrist approved these changes
@addaleax addaleax Awaiting requested review from addaleax
+2 more reviewers
@bmeck bmeck bmeck approved these changes
@MylesBorins MylesBorins MylesBorins approved these changes
Reviewers whose approvals may not affect merge requirements

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

7 participants

@guybedford @ljharb @GeoffreyBooth @nodejs-github-bot @bmeck @MylesBorins @hybrist
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.