Have @babel/register explicitly skip re-entrant plugins/presets.

This commit is contained in:
Logan Smyth 2018-03-25 14:22:11 -07:00
parent 40e38646e4
commit 1dbed5f458
2 changed files with 45 additions and 1 deletions

View File

@ -100,3 +100,34 @@ Disable the cache.
```sh
BABEL_DISABLE_CACHE=1 babel-node script.js
```
## Compiling plugins and presets on the fly
`@babel/register` uses Node's `require()` hook system to compile files
on the fly when they are loaded. While this is quite helpful overall, it means
that there can be confusing cases where code within a `require()` hook causes
_more_ calls to `require`, causing a dependency cycle. In Babel's case for
instance, this could mean that in the process of Babel trying to compile a
user's file, Babel could end up trying to compile itself _as it is loading_.
To avoid this problem, this module explicitly disallows re-entrant compilation,
e.g. Babel's own compilation logic explicitly cannot trigger further compilation
of any other files on the fly. The downside of this is that if you want to
define a plugin or preset that is itself live-compiled, the process is
complicated.
The crux of it is that your own code needs to load the plugin/preset first.
Assuming the plugin/preset loads all of its dependencies up front, what you'll
want to do is:
```
require("@babel/register")({
// ...
});
require("./my-plugin");
```
Because it is your own code that triggered the load, and not the logic within
`@babel/register` itself, this should successfully compile any plugin/preset
that that loads synchronously.

View File

@ -80,9 +80,22 @@ function compile(code, filename) {
return cached.code;
}
let compiling = false;
function compileHook(code, filename) {
if (compiling) return code;
try {
compiling = true;
return compile(code, filename);
} finally {
compiling = false;
}
}
function hookExtensions(exts) {
if (piratesRevert) piratesRevert();
piratesRevert = addHook(compile, { exts, ignoreNodeModules: false });
piratesRevert = addHook(compileHook, { exts, ignoreNodeModules: false });
}
export function revert() {