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

fix: babel-register transform internal dependencies #12665

Merged

Conversation

overlookmotel
Copy link
Contributor

@overlookmotel overlookmotel commented Jan 20, 2021

Q                       A
Fixed Issues? Fixes #11964, Fixes #12662
Patch: Bug Fix? Yes
Major: Breaking Change? No
Minor: New Feature? No
Tests Added + Pass? Yes
Documentation PR Link n/a
Any Dependency Changes? No
License MIT

As discussed in issues #11964 and #12662, babel-register fails to transform modules which Babel uses internally. In a few cases (e.g. require('to-fast-properties')), this can cause babel-register to throw an error.

These issues arise when babel-register is called with ignore: [] option so it transforms the contents of node_modules.

There are two reasons why modules don't get transformed:

  1. The modules are require()-ed within babel-register before the pirates hook is activated.
  2. The modules are lazily-required during transform, and register bails out of transforming them to prevent an infinite loop.

This PR fixes both problems.

Prior to loading lib/node.js, it creates a mock module cache. All require() calls within babel register use this internal module cache, so untransformed modules are not populated in the global (normal) module cache. When these modules are loaded externally, they pass through register's transform.

Usually, messing around with Node's module cache would be considered pretty hacky, but in the context of babel-register, it seems more reasonable to me.

There is a special case for source-map-support package which is shared between both the global module cache and register's internal module cache. This is necessary as the module is stateful. It would be ideal to transform this module too, but the workaround necessary to do so is pretty tortuous, so I've omitted it from this PR.

@babel-bot
Copy link
Collaborator

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/37944/

@codesandbox-ci
Copy link

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit a438bf4:

Sandbox Source
babel-repl-custom-plugin Configuration
babel-plugin-multi-config Configuration

@JLHwung JLHwung added pkg: register PR: Bug Fix 🐛 A type of pull request used for our changelog categories labels Jan 20, 2021
@overlookmotel
Copy link
Contributor Author

Not sure why the last two CircleCI jobs have stalled.

Copy link
Contributor

@JLHwung JLHwung left a comment

Choose a reason for hiding this comment

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

Thanks!

@nicolo-ribaudo
Copy link
Member

Not sure why the last two CircleCI jobs have stalled.

Don't worry, we only run them manually when needed

Copy link
Member

@nicolo-ribaudo nicolo-ribaudo left a comment

Choose a reason for hiding this comment

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

Thanks! I don't really like having to do this, but I can see why it's needed and the solution seems solid.

In the future, when adding ESM support for @babel/register, I'd like to experiment with moving it to a Worker and it will hopefully also properly solve this.

@nicolo-ribaudo nicolo-ribaudo changed the title fix: babel-register transform modules used internally fix: babel-register transform internal dependencies Jan 22, 2021
@nicolo-ribaudo nicolo-ribaudo merged commit 22eb99b into babel:main Jan 22, 2021
@overlookmotel
Copy link
Contributor Author

Thanks very much for merging this so swiftly.

Yes, it's a pretty ugly solution, but I couldn't see a better one.

If babel-register was implemented as a Node ESM loader then the compilation code would execute in a separate context, so they wouldn't be sharing the same module cache, and this problem would disappear.

However, an annoyance with the ESM loaders spec at present is, according to the docs, "When hooks are used they only apply to ES module loading and not to any CommonJS modules loaded." So to support both ESM and CJS, as far as I can see, you'd need two separate babel-register implementations, and it could get messy where an ESM module imports CommonJS and vice-versa.

I've been meaning to raise this as an issue on NodeJS but not got around to it yet.

@overlookmotel
Copy link
Contributor Author

Have just opened a small follow-up PR #12674 with a slight tweak to implementation.

@nicolo-ribaudo
Copy link
Member

I've been meaning to raise this as an issue on NodeJS but not got around to it yet.

If you end up opening it please ping me! I have been privately asking to Node.js maintainers if it's possible do use a single implementation for CJS and ESM, because it would greatly simplify our implementation.

@github-actions github-actions bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Jun 5, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 5, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated A closed issue/PR that is archived due to age. Recommended to make a new issue pkg: register PR: Bug Fix 🐛 A type of pull request used for our changelog categories
Projects
None yet
4 participants